DUNE-ACFEM (unstable)

operationtraits.hh
1#ifndef __DUNE_ACFEM_TENSORS_OPERATIONTRAITS_HH__
2#define __DUNE_ACFEM_TENSORS_OPERATIONTRAITS_HH__
3
6#include "../mpl/compare.hh"
7#include "../expressions/storage.hh"
8#include "../expressions/expressionoperations.hh"
9#include "expressionoperations.hh"
10#include "operations/einsum.hh"
11#include "operations/product.hh"
12#include "operations/restriction.hh"
13#include "operations/transpose.hh"
14
15namespace Dune {
16
17 namespace ACFem {
18
34 template<std::size_t... Dims, std::size_t... PivotIndices>
35 struct OperationTraits<RestrictionOperation<IndexSequence<Dims...>, IndexSequence<PivotIndices...> > >
36 {
37 static_assert(sizeof...(Dims) == sizeof...(PivotIndices),
38 "Size of pivot indices must match size of co-dimension.");
39
40 using PivotSequence = IndexSequence<PivotIndices...>;
41 using InvertibleOperation = void; // restrictions are not invertible
42 using OperationType = RestrictionOperation<IndexSequence<Dims...>, PivotSequence>;
43
44 template<class T, class SFINAE = void>
45 struct HasOperation
46 : FalseType
47 {
48 // assume elementary type if no restriction operation is defined.
49 using ResultType = T;
50 };
51
52 template<class T>
53 struct HasOperation<T, std::enable_if_t<(sizeof(decltype(restriction<Dims...>(std::declval<T>(), PivotSequence{}))) >= 0)> >
54 : TrueType
55 {
56 using ResultType = std::decay_t<decltype(restriction<Dims...>(std::declval<T>(), PivotSequence{}))>;
57 };
58
59 template<class T>
60 using ResultType = typename HasOperation<T>::ResultType;
61
62 // Assuming only real numbers.
63 template<class Sign>
64 static constexpr auto signPropagation(const Sign&)
65 {
66 return Sign{};
67 }
68
69 static std::string name()
70 {
71 return "rst<"+toString(IndexSequence<Dims...>{})+"@"+toString(PivotSequence{})+">";
72 }
73
74 template<class Order>
75 static constexpr auto polynomialOrder(Order oldOrder)
76 {
77 return oldOrder;
78 }
79
80 template<class T, class... Rest, std::enable_if_t<HasOperation<T>::value, int> = 0>
81 auto operator()(T&& t, Rest&&...) const
82 {
83 return restriction<Dims...>(std::forward<T>(t), PivotSequence{});
84 }
85
86 template<class T, class... Rest, std::enable_if_t<!HasOperation<T>::value, int> = 0>
87 constexpr decltype(auto) operator()(T&& t, Rest&&...) const
88 {
89 return std::forward<T>(t);
90 }
91
92 using PivotType = PivotSequence;
93 PivotType pivotIndices_;
94 };
95
96 template<std::size_t... Dims>
97 struct OperationTraits<RestrictionOperation<IndexSequence<Dims...>, IndexSequence<> > >
98 {
99 private:
100 using ThisType = OperationTraits;
101 public:
102 using InvertibleOperation = void; // restrictions are not invertible
103 using OperationType = RestrictionOperation<IndexSequence<Dims...>, IndexSequence<> >;
104
105 OperationTraits()
106 : pivotIndices_({{}})
107 {}
108
109 OperationTraits(const OperationTraits& other)
110 : pivotIndices_(other.pivotIndices_)
111 {}
112
113 OperationTraits(OperationTraits&& other)
114 : pivotIndices_(std::move(other.pivotIndices_))
115 {}
116
117 template<class List, std::size_t... I, std::enable_if_t<IsTupleLike<List>::value, int> = 0>
118 OperationTraits(const List& l, IndexSequence<I...>)
119 : pivotIndices_({{ (IndexType)get<I>(l)... }})
120 {}
121
122 template<class List, std::enable_if_t<IsTupleLike<List>::value, int> = 0>
123 OperationTraits(const List& l)
124 : OperationTraits(l, MakeSequenceFor<List>{})
125 {}
126
127 template<class T, std::size_t N, std::size_t... I>
128 OperationTraits(const T (&l)[N], IndexSequence<I...>)
129 : pivotIndices_({{ (IndexType)get<I>(l)... }})
130 {}
131
132 template<class I, std::size_t N>
133 OperationTraits(const I (&l)[N])
134 : OperationTraits(l, MakeIndexSequence<N>{})
135 {}
136
137 template<class T, class SFINAE = void>
138 struct HasOperation
139 : FalseType
140 {
141 // assume elementary type if no restriction operation is defined.
142 using ResultType = T;
143 };
144
145 template<class T>
146 struct HasOperation<T, std::enable_if_t<sizeof(decltype(restriction<Dims...>(std::declval<T>()))) >= 0> >
147 : TrueType
148 {
149 using ResultType = std::decay_t<decltype(restriction<Dims...>(std::declval<T>()))>;
150 };
151
152 template<class T>
153 using ResultType = typename HasOperation<T>::ResultType;
154
155 // Assuming only real numbers.
156 template<class Sign>
157 static constexpr auto signPropagation(const Sign&)
158 {
159 return Sign{};
160 }
161
162 std::string name() const
163 {
164 return "rst<"+toString(IndexSequence<Dims...>{})+"@["+toString(pivotIndices_)+"]>";
165 }
166
167 template<class Order>
168 static constexpr auto polynomialOrder(Order oldOrder)
169 {
170 return oldOrder;
171 }
172
173 public:
174 template<class T, class... Rest, std::enable_if_t<HasOperation<T>::value, int> = 0>
175 constexpr auto operator()(T&& t, Rest&&...) const
176 {
177 return restriction<Dims...>(std::forward<T>(t), pivotIndices_);
178 }
179
180 template<class T, class... Rest, std::enable_if_t<!HasOperation<T>::value, int> = 0>
181 constexpr decltype(auto) operator()(T&& t, Rest&&...) const
182 {
183 return std::forward<T>(t);
184 }
185
186 using IndexType = unsigned;
187 using PivotType = std::array<IndexType, sizeof...(Dims)>;
188 PivotType pivotIndices_;
189 };
190
192
198 template<class Perm>
199 struct OperationTraits<TransposeOperation<Perm> >
200 {
203
204 template<class T, class SFINAE = void>
205 struct HasOperation
206 : FalseType
207 {
208 // assume elementary type if no restriction operation is defined.
209 using ResultType = T;
210 };
211
212 template<class T>
213 struct HasOperation<T, VoidType<decltype(transpose(std::declval<T>(), Perm{}))> >
214 : TrueType
215 {
216 using ResultType = std::decay_t<decltype(transpose(std::declval<T>(), Perm{}))>;
217 };
218
219 // Assuming only real numbers.
220 template<class Sign>
221 static constexpr auto signPropagation(const Sign&)
222 {
223 return Sign{};
224 }
225
226 static std::string name()
227 {
228 return "tr<"+toString(Perm{})+">";
229 }
230
231 template<class Order>
232 static constexpr auto polynomialOrder(Order oldOrder)
233 {
234 return oldOrder;
235 }
236
237 template<class T>
238 auto operator()(T&& t) const
239 {
240 return transpose(std::forward<T>(t), Perm{});
241 }
242
243 template<class T, std::enable_if_t<!HasOperation<T>::value, int> = 0>
244 constexpr decltype(auto) operator()(T&& t) const
245 {
246#if 0
247 if (!IsScalar<T>::value) {
248 std::clog << "no transpose " << toString(Perm{}) << " for " << t.name() << std::endl;
249 }
250#endif
251 assert(IsScalar<T>::value);
252 return std::forward<T>(t);
253 }
254 };
255
257
262 template<class Sig>
263 struct OperationTraits<ReshapeOperation<Sig> >
264 {
265 using InvertibleOperation = void;
267
268 template<class T, class SFINAE = void>
269 struct HasOperation
270 : FalseType
271 {
272 // assume elementary type if no restriction operation is defined.
273 using ResultType = T;
274 };
275
276 template<class T>
277 struct HasOperation<T, VoidType<decltype(reshape(std::declval<T>(), Sig{}))> >
278 : TrueType
279 {
280 using ResultType = std::decay_t<decltype(reshape(std::declval<T>(), Sig{}))>;
281 };
282
283 // Assuming only real numbers.
284 template<class Sign>
285 static constexpr auto signPropagation(const Sign&)
286 {
287 return Sign{};
288 }
289
290 static std::string name()
291 {
292 return "reshape<"+toString(Sig{})+">";
293 }
294
295 template<class Order>
296 static constexpr auto polynomialOrder(Order oldOrder)
297 {
298 return oldOrder;
299 }
300
301 template<class T>
302 auto operator()(T&& t) const
303 {
304 return reshape(std::forward<T>(t), Sig{});
305 }
306
307 template<class T, std::enable_if_t<!HasOperation<T>::value, int> = 0>
308 constexpr decltype(auto) operator()(T&& t) const
309 {
310 assert(IsScalar<T>::value);
311 return std::forward<T>(t);
312 }
313 };
314
316
329 template<class Pos1, class Pos2, class Dims>
330 struct OperationTraits<EinsumOperation<Pos1, Pos2, Dims> >
331 {
332 static_assert(Pos1::size() == Pos2::size() && Pos2::size() == Dims::size(),
333 "Number of contraction indices must coincide for Einstein-summation.");
334
335 using InvertibleOperation = void;
337
338 using LeftIndexPositions = Pos1;
339 using RightIndexPositions = Pos2;
340 using Dimensions = Dims;
341
342 template<class T0, class T1>
344 SequenceSliceComplement<typename TensorTraits<T1>::Signature, RightIndexPositions> >;
345
346 static constexpr Dimensions dimensions()
347 {
348 return Dimensions{};
349 }
350
351 static constexpr std::size_t contractionDimension()
352 {
353 return prod(dimensions());
354 }
355
356 template<class T1, class T2, class SFINAE = void>
357 struct HasOperation
358 : FalseType
359 {
360 // assume elementary type if no restriction operation is defined.
361 using ResultType = std::decay_t<decltype(std::declval<T1>() * std::declval<T2>())>;
362 };
363
364 template<class T1, class T2>
365 struct HasOperation<T1, T2, VoidType<decltype(einsum<Pos1, Pos2>(std::declval<T1>(), std::declval<T2>()))> >
366 : TrueType
367 {
368 using ResultType = std::decay_t<decltype(einsum<Pos1, Pos2>(std::declval<T1>(), std::declval<T2>()))>;
369 };
370
371 template<class T1, class T2>
372 using ResultType = typename HasOperation<T1, T2>::ResultType;
373
374 template<class Order1, class Order2>
375 static constexpr auto polynomialOrder(Order1 order1, Order2 order2)
376 {
377 return order1 + order2;
378 }
379
380 static constexpr std::size_t dim = Prod<Dims>::value;
381
382 // in arbitraty dimension this is a scalar product, hence the
383 // nonZero property need not be maintained.
384 template<class S1, class S2>
385 static constexpr auto signPropagation(const S1&, const S2&)
386 {
387 return ExpressionSign<// non-singular
388 (dim == 1
389 &&
390 S1::isNonSingular && S2::isNonSingular
391 &&
392 (((S1::reference >= 0) && S1::isSemiPositive)
393 ||
394 ((S1::reference <= 0) && S1::isSemiNegative))
395 &&
396 (((S2::reference >= 0) && S2::isSemiPositive)
397 ||
398 ((S2::reference <= 0) && S2::isSemiNegative))),
399 // >= dim * S1::reference * S2::reference
400 ((S1::reference*S2::reference >= 0)
401 &&
402 ((S1::isSemiPositive && S2::isSemiPositive)
403 ||
404 (S1::isSemiNegative && S2::isSemiNegative))),
405 // <= dim * S1::reference * S2::reference
406 ((S1::reference*S2::reference <= 0)
407 &&
408 ((S1::isSemiPositive && S2::isSemiNegative)
409 ||
410 (S1::isSemiNegative && S2::isSemiPositive))),
411 // new reference
412 dim * S1::reference * S2::reference>{};
413 }
414
415 static std::string name()
416 {
417 return "*"+(Pos1::size() > 0 ? "["+toString(Pos1{})+"]["+toString(Pos2{})+"]" : "");
418 }
419
420 template<class T1, class T2, std::enable_if_t<HasOperation<T1, T2>::value, int> = 0>
421 constexpr auto operator()(T1&& t1, T2&& t2) const
422 {
423 return einsum<Pos1, Pos2>(std::forward<T1>(t1), std::forward<T2>(t2));
424 }
425
426 // degenerate to ordinary product for elementary operands
427 template<class T1, class T2, std::enable_if_t<!HasOperation<T1, T2>::value, int> = 0>
428 constexpr auto operator()(T1&& t1, T2&& t2) const
429 {
430 return std::forward<T1>(t1) * std::forward<T2>(t2);
431 }
432 };
433
435
448 template<class Pos1, class Pos2, class Dims>
449 struct OperationTraits<TensorProductOperation<Pos1, Pos2, Dims> >
450 {
451 static_assert(Pos1::size() == Pos2::size() && Pos2::size() == Dims::size(),
452 "Number of contraction indices must coincide for product operation.");
453
454 using InvertibleOperation = void;
456
457 using LeftIndexPositions = Pos1;
458 using RightIndexPositions = Pos2;
459 using Dimensions = Dims;
460
461 template<class T1, class T2, class SFINAE = void>
462 struct HasOperation
463 : FalseType
464 {
465 // assume elementary type if no restriction operation is defined.
466 using ResultType = std::decay_t<decltype(std::declval<T1>() * std::declval<T2>())>;
467 };
468
469 template<class T1, class T2>
470 struct HasOperation<T1, T2, std::enable_if_t<(sizeof(decltype(multiply<Pos1, Pos2>(std::declval<T1>(), std::declval<T2>()))) >= 0)> >
471 : TrueType
472 {
473 using ResultType = std::decay_t<decltype(multiply<Pos1, Pos2>(std::declval<T1>(), std::declval<T2>()))>;
474 };
475
476 template<class T1, class T2>
477 using ResultType = typename HasOperation<T1, T2>::ResultType;
478
479 template<class Order1, class Order2>
480 static constexpr auto polynomialOrder(Order1 order1, Order2 order2)
481 {
482 return order1 + order2;
483 }
484
485 static constexpr std::size_t dim = 1; // pointwise, no summation
486
487 // in arbitraty dimension this is a scalar product, hence the
488 // nonZero property need not be maintained.
489 template<class S1, class S2>
490 static constexpr auto signPropagation(const S1&, const S2&)
491 {
492 return ExpressionSign<// non-singular
493 (dim == 1
494 &&
495 S1::isNonSingular && S2::isNonSingular
496 &&
497 (((S1::reference >= 0) && S1::isSemiPositive)
498 ||
499 ((S1::reference <= 0) && S1::isSemiNegative))
500 &&
501 (((S2::reference >= 0) && S2::isSemiPositive)
502 ||
503 ((S2::reference <= 0) && S2::isSemiNegative))),
504 // >= dim * S1::reference * S2::reference
505 ((S1::reference*S2::reference >= 0)
506 &&
507 ((S1::isSemiPositive && S2::isSemiPositive)
508 ||
509 (S1::isSemiNegative && S2::isSemiNegative))),
510 // <= dim * S1::reference * S2::reference
511 ((S1::reference*S2::reference <= 0)
512 &&
513 ((S1::isSemiPositive && S2::isSemiNegative)
514 ||
515 (S1::isSemiNegative && S2::isSemiPositive))),
516 // new reference
517 dim * S1::reference * S2::reference>{};
518 }
519
520 static std::string name()
521 {
522 return "."+(Pos1::size() > 0 ? "["+toString(Pos1{})+"]["+toString(Pos2{})+"]" : "");
523 }
524
525 template<class T1, class T2>
526 auto operator()(T1&& t1, T2&& t2) const
527 {
528 return multiply<Pos1, Pos2>(std::forward<T1>(t1), std::forward<T2>(t2));
529 }
530
531 // degenerate to ordinary product for elementary operands
532 template<class T1, class T2, std::enable_if_t<!HasOperation<T1, T2>::value, int> = 0>
533 constexpr auto operator()(T1&& t1, T2&& t2) const
534 {
535 return std::forward<T1>(t1) * std::forward<T2>(t2);
536 }
537 };
538
539 template<class T>
540 struct SquareTraits<T, std::enable_if_t<(HasTensorTraitsV<T> && TensorTraits<T>::rank > 0)> >
541 {
542 using ExplodeFunctor = OperationTraits<
546 typename TensorTraits<T>::Signature>
547 >;
548 };
549
550 template<class T>
551 struct SquareTraits<T, std::enable_if_t<(HasTensorTraitsV<T> && TensorTraits<T>::rank == 0)> >
552 {
553 using ExplodeFunctor = Tensor::ScalarEinsumFunctor;
554 };
555
557
559
561
562 } // NS ACFem
563
564} // NS Dune
565
566#endif // __DUNE_ACFEM_TENSORS_OPERATIONTRAITS_HH__
constexpr std::size_t size()
Gives the number of elements in tuple-likes and std::integer_sequence.
Definition: size.hh:73
MakeIndexSequence< size< T >()> MakeSequenceFor
Make a simple index sequence of the size of the argument, which may be anything for which size<T>() e...
Definition: generators.hh:41
MakeSequence< std::size_t, N, Offset, Stride, Repeat > MakeIndexSequence
Make a sequence of std::size_t elements.
Definition: generators.hh:34
typename SequenceCatHelper2< S... >::Type SequenceCat
Concatenate the given sequences, in order, to <S0, S1, ... >.
Definition: transform.hh:220
auto restriction(T &&t, Indices &&indices, Seq< IndexPositions... >=Seq< IndexPositions... >{})
Generate a compile-time dynamic restriction with position given from a tuple-like object.
Definition: operandpromotion.hh:241
constexpr decltype(auto) einsum(T1 &&t1, T2 &&t2)
Tensor contraction for proper tensors.
Definition: einsum.hh:561
constexpr decltype(auto) transpose(T &&t, Seq< Perm... >=Seq< Perm... >{})
Promote operands to tensor transposition operation.
Definition: operandpromotion.hh:309
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
STL namespace.
Einstein summation, i.e.
Definition: expressionoperations.hh:308
A class mainting the sign of an expression during operations.
Definition: sign.hh:30
std::true_type if F is an "elementary" scalar.
Definition: typetraits.hh:35
Signature of index positions of tensors.
Definition: expressionoperations.hh:232
Component-wise product over given index-set.
Definition: expressionoperations.hh:389
Permutation of index positions of tensors.
Definition: expressionoperations.hh:167
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)