DUNE-ACFEM (unstable)

kronecker.hh
1#ifndef __DUNE_ACFEM_TENSORS_MODULES_KRONECKER_HH__
2#define __DUNE_ACFEM_TENSORS_MODULES_KRONECKER_HH__
3
4#include "../../mpl/assign.hh"
5#include "../tensorbase.hh"
6#include "../expressiontraits.hh"
7
8namespace Dune {
9
10 namespace ACFem {
11
12 namespace Tensor {
13
22 template<class Signature, class PivotIndices, class Field>
23 class KroneckerDelta;
24
25 template<class Signature, class PivotIndices, class Field>
26 struct HasSpecializedExpressionTraits<KroneckerDelta<Signature, PivotIndices, Field> >
27 : TrueType
28 {};
29
33 template<class Field, std::size_t... Dimensions, std::size_t... PivotIndices>
34 class KroneckerDelta<Seq<Dimensions...>, Seq<PivotIndices...>, Field>
35 : public TensorBase<FloatingPointClosure<Field>, Seq<Dimensions...>, KroneckerDelta<Seq<Dimensions...>, Seq<PivotIndices...>, Field> >
36 , public Expressions::SelfExpression<KroneckerDelta<Seq<Dimensions...>, Seq<PivotIndices...>, Field> >
37 , public MPL::UniqueTags<ConstantExpression,
38 ConditionalType<IsTypedValue<Field>::value, TypedValueExpression, void> >
39 {
40 using BaseType = TensorBase<FloatingPointClosure<Field>, Seq<Dimensions...>, KroneckerDelta<Seq<Dimensions...>, Seq<PivotIndices...>, Field> >;
41 public:
42 using BaseType::rank;
43 using typename BaseType::Signature;
44 using typename BaseType::FieldType;
45 using PivotSequence = Seq<PivotIndices...>;
46 using ValueType = Field;
47
51 template<class... Dims,
52 std::enable_if_t<(sizeof...(Dims) == rank
53 &&
55 , int> = 0>
56 FieldType operator()(Dims... indices) const
57 {
58 if (std::make_tuple((std::size_t)indices...) != std::make_tuple(PivotIndices...)) {
59 return FieldType(0);
61 return FieldType(ValueType{});
62 } else {
63 return FieldType(1);
64 }
65 }
66
68 template<std::size_t... Indices,
69 std::enable_if_t<sizeof...(Indices) == rank, int> = 0>
70 decltype(auto) operator()(Seq<Indices...>) const
71 {
72 using ReturnType = ConditionalType<isZero<Indices...>(),
73 IntFraction<0>,
74 ConditionalType<IsTypedValue<ValueType>::value,
75 ValueType,
76 IntFraction<1> > >;
77 return ReturnType{};
78 }
79
80 private:
81 template<std::size_t... Indices, std::size_t... Pos>
82 static bool constexpr isZeroExpander(Seq<Indices...>, Seq<Pos...>)
83 {
84 return !(... && (Indices == Get<Pos, Seq<PivotIndices...> >::value));
85 }
86
87 public:
88 template<std::size_t... Indices, class Pos = MakeIndexSequence<sizeof...(Indices)> >
89 static bool constexpr isZero(Seq<Indices...> = Seq<Indices...>{}, Pos = Pos{})
90 {
91 // Truncate Pos to size of Indices...
92 using RealPos = HeadPart<sizeof...(Indices), Pos>;
93
94 return isZeroExpander(Seq<Indices...>{}, RealPos{});
95 }
96
97 std::string name() const
98 {
99 return "delta<"+toString(Signature{})+"@["+toString(PivotSequence{})+"]>";
100 }
101
102 static constexpr auto lookAt()
103 {
104 return PivotSequence{};
105 }
106 };
107
111 template<class Field, std::size_t D0, std::size_t... RestDims>
112 class KroneckerDelta<Seq<D0, RestDims...>, Seq<>, Field>
113 : public TensorBase<FloatingPointClosure<Field>, Seq<D0, RestDims...>, KroneckerDelta<Seq<D0, RestDims...>, Seq<>, Field> >
114 , public TerminalExpression
115 , public ConstantExpression
116 {
117 using BaseType = TensorBase<FloatingPointClosure<Field>, Seq<D0, RestDims...>, KroneckerDelta<Seq<D0, RestDims...>, Seq<>, Field> >;
118 public:
119 using BaseType::rank;
120 using typename BaseType::Signature;
121 using typename BaseType::FieldType;
122 using ValueType = Field;
123
124 private:
126 template<std::size_t... I, class T>
127 KroneckerDelta(T&& tuple, Seq<I...>&&)
128 : pivotIndices_({{ (std::size_t)std::get<I>(tuple)... }})
129 {}
130
131 public:
140 template<class T,
141 std::enable_if_t<(IsTupleLike<T>::value
142 && size<T>() == rank
144 ), int> = 0>
145 KroneckerDelta(T&& tuple)
146 : KroneckerDelta(std::forward<T>(tuple), MakeSequenceFor<T>{})
147 {}
148
156 template<class... Indices,
157 std::enable_if_t<(sizeof...(Indices) != 0
158 &&
159 sizeof...(Indices) == rank
160 &&
161 IsIntegralPack<Indices...>::value
162 ), int> = 0>
163 KroneckerDelta(Indices... indices)
164 : pivotIndices_({{ (std::size_t)indices... }})
165 {}
166
170 template<class... Dims,
171 std::enable_if_t<(sizeof...(Dims) == rank
172 &&
174 , int> = 0>
175 FieldType operator()(Dims... indices) const
176 {
177 if (std::array<std::size_t, rank>({{ (std::size_t)indices... }}) != pivotIndices_) {
178 return FieldType(0);
180 return FieldType(ValueType{});
181 } else {
182 return FieldType(1);
183 }
184 }
185
189 template<std::size_t... Indices,
190 std::enable_if_t<sizeof...(Indices) == rank, int> = 0>
191 decltype(auto) operator()(Seq<Indices...>) const
192 {
193 return (*this)(Indices...);
194 }
195
196 template<std::size_t... Indices, class Pos = MakeIndexSequence<sizeof...(Indices)> >
197 static bool constexpr isZero(Seq<Indices...> = Seq<Indices...>{}, Pos = Pos{})
198 {
199 return false; // we just do not know ...
200 }
201
206 template<class... Indices,
207 std::enable_if_t<((sizeof...(Indices) > 0)
208 && IsIntegralPack<Indices...>::value)
209 , int> = 0>
210 void lookAt(Indices... indices)
211 {
212 static_assert(sizeof...(Indices) == rank,
213 "The number of pivot indices must match the co-dimension.");
214 pivotIndices_ = {{ (std::size_t)indices... }};
215 }
216
222 template<class T,
223 std::enable_if_t<(IsTupleLike<T>::value)
224 , int> = 0>
225 void lookAt(T&& tuple)
226 {
227 static_assert(size<T>() == rank,
228 "The number of pivot indices must match the co-dimension.");
229 ACFem::assign(pivotIndices_, tuple);
230 }
231
233 const std::array<std::size_t, rank>& lookAt() const&
234 {
235 return pivotIndices_;
236 }
237
238 std::string name() const
239 {
240 return "delta<"+toString(Signature{})+"@["+toString(pivotIndices_)+"]>";
241 }
242
243 private:
244 std::array<std::size_t, rank> pivotIndices_;
245 };
246
248 template<class T, class SFINAE = void>
250 : FalseType
251 {};
252
253 template<class T>
256 {};
257
258 template<std::size_t... Pos, class PivotIndices, class Field>
259 struct IsKroneckerDelta<KroneckerDelta<Seq<Pos...>, PivotIndices, Field> >
260 : TrueType
261 {};
262
263 template<class T>
264 struct IsConstKroneckerDelta
265 : FalseType
266 {};
267
268 template<class T>
269 struct IsConstKroneckerDelta<T&>
270 : IsConstKroneckerDelta<std::decay_t<T> >
271 {};
272
273 template<class T>
274 struct IsConstKroneckerDelta<T&&>
275 : IsConstKroneckerDelta<std::decay_t<T> >
276 {};
277
281 template<std::size_t... Pos, std::size_t... Pivot, class Field>
282 struct IsConstKroneckerDelta<KroneckerDelta<Seq<Pos...>, Seq<Pivot...>, Field> >
283 : BoolConstant<(sizeof...(Pos) == sizeof...(Pivot))>
284 {};
285
286 template<class T>
287 struct IsDiagonalKroneckerDelta
288 : FalseType
289 {};
290
291 template<class T>
292 struct IsDiagonalKroneckerDelta<T&>
293 : IsDiagonalKroneckerDelta<T>
294 {};
295
296 template<class T>
297 struct IsDiagonalKroneckerDelta<T&&>
298 : IsDiagonalKroneckerDelta<T>
299 {};
300
301 template<std::size_t... Pos, std::size_t Pivot0, std::size_t... Pivot, class Field>
302 struct IsDiagonalKroneckerDelta<KroneckerDelta<Seq<Pos...>, Seq<Pivot0, Pivot...>, Field> >
303 : BoolConstant<(... && (Pivot0 == Pivot))>
304 {};
305
306 template<class T>
307 using PivotSequence = typename std::decay_t<T>::PivotSequence;
308
309 template<std::size_t... Index, class Dims, class F = Expressions::Closure,
310 std::enable_if_t<IsSequence<Dims>::value, int> = 0>
311 auto kroneckerDelta(Dims = Dims{}, Seq<Index...> = Seq<Index...>{}, F closure = F{})
312 {
313 static_assert(Dims::size() == sizeof...(Index),
314 "Kronecker-Delta needs an index tuple of the size of the rank of the tensor.");
315 static_assert(Seq<Index...>{} < Dims{},
316 "Index tuple not in range of tensor dimensions");
317
318 return closure(KroneckerDelta<Dims, Seq<Index...>, IntFraction<1> >{});
319 }
320
321 template<std::size_t... Dimensions, std::size_t... Index, class F = Expressions::Closure>
322 auto kroneckerDelta(Seq<Dimensions...>, Seq<Index...>, F closure = F{})
323 {
324 static_assert(sizeof...(Dimensions) == sizeof...(Index),
325 "Kronecker-Delta needs an index tuple of the size of the rank of the tensor.");
326 static_assert(Seq<Index...>{} < Seq<Dimensions...>{},
327 "Index tuple not in range of tensor dimensions");
328
329 return closure(KroneckerDelta<Seq<Dimensions...>, Seq<Index...>, IntFraction<1> >{});
330 }
331
332 template<class T, std::size_t... Index, class F = Expressions::Closure,
333 std::enable_if_t<IsTensorOperand<T>::value, int> = 0>
334 auto kroneckerDelta(T&&, Seq<Index...>, F = F{})
335 {
336 return kroneckerDelta(typename TensorTraits<T>::Signature{}, Seq<Index...>{}, F{});
337 }
338
339 template<std::size_t... Dimensions, class Tuple, class F = Expressions::Closure,
340 std::enable_if_t<IsTupleLike<Tuple>::value, int> = 0>
341 auto kroneckerDelta(Seq<Dimensions...>, const Tuple& tuple, F closure = F{})
342 {
343 static_assert(sizeof...(Dimensions) == size<Tuple>(),
344 "Kronecker-Delta needs an index tuple of the size of the rank of the tensor.");
345 return closure(KroneckerDelta<Seq<Dimensions...>, Seq<>, IntFraction<1> >(tuple));
346 }
347
348 template<std::size_t... Dimensions, class... Indices,
349 std::enable_if_t<IsIntegralPack<Indices...>::value, int> = 0>
350 auto kroneckerDelta(Seq<Dimensions...>, Indices... indices)
351 {
352 static_assert(sizeof...(Dimensions) == sizeof...(Indices),
353 "Kronecker-Delta needs an index tuple of the size of the rank of the tensor.");
354 return expressionClosure(KroneckerDelta<Seq<Dimensions...>, Seq<>, IntFraction<1> >(indices...));
355 }
356
358
360
361 } // NS Tensor
362
363 using Tensor::kroneckerDelta;
364
365 template<class Field, class Signature, class Indices>
366 struct ExpressionTraits<Tensor::KroneckerDelta<Signature, Indices, Field> >
367 : ExpressionTraits<Field>
368 {
369 private:
370 using BaseType = ExpressionTraits<Field>;
371 public:
372 using ExpressionType = Tensor::KroneckerDelta<Signature, Indices, Field>;
373 static constexpr bool isOne = BaseType::isOne && ExpressionType::rank == 0;
374 static constexpr bool isMinusOne = BaseType::isMinusOne && ExpressionType::rank == 0;
375 static constexpr bool isNonZero = BaseType::isNonZero && ExpressionType::rank == 0;
376 static constexpr bool isPositive = BaseType::isPositive && ExpressionType::rank == 0;
377 static constexpr bool isNegative = BaseType::isNegative && ExpressionType::rank == 0;
378 static constexpr bool isNonSingular = ExpressionType::rank == 0;
379 using Sign = ExpressionSign<isNonZero, BaseType::isSemiPositive, BaseType::isSemiNegative>;
380
381 static constexpr bool isIndependent = BaseType::isIndependent;
382 static constexpr bool isConstant = BaseType::isConstant && !std::is_same<Indices, Tensor::Seq<> >::value;
383 static constexpr bool isTypedValue = BaseType::isTypedValue && !std::is_same<Indices, Tensor::Seq<> >::value;
384 };
385
386 namespace Expressions {
387
388 template<class Field, class Signature, std::size_t Pivot0, std::size_t... Pivot>
389 constexpr inline std::size_t WeightV<Tensor::KroneckerDelta<Signature, Tensor::Seq<Pivot0, Pivot...>, Field> > = (Pivot0 + ... + Pivot) + 1000*(... && (Pivot0 != Pivot));
390
391 }
392
393 } // NS ACFem
394
395 template<class Field, class Signature, class Indices>
396 struct FieldTraits<ACFem::Tensor::KroneckerDelta<Signature, Indices, Field> >
397 : FieldTraits<std::decay_t<Field> >
398 {};
399
400} // NS Dune
401
402#endif // __DUNE_VECTOR_EXPRESSIONS_KRONECKER_HH__
KroneckerDelta(Indices... indices)
Constructor from a given index pack of lookAt() indices.
Definition: kronecker.hh:163
decltype(auto) operator()(Seq< Indices... >) const
Constant access from index-sequence.
Definition: kronecker.hh:191
FieldType operator()(Dims... indices) const
Insert the current view-indices at their proper positions and foward to the underlying "host" tensor.
Definition: kronecker.hh:175
KroneckerDelta(T &&tuple)
Constructor from a given tuple-like index collection.
Definition: kronecker.hh:145
void lookAt(Indices... indices)
"Move" the view to the given index pack.
Definition: kronecker.hh:210
void lookAt(T &&tuple)
"Move" pivot index to the specified values.
Definition: kronecker.hh:225
const std::array< std::size_t, rank > & lookAt() const &
Return the array of indices currently looking at.
Definition: kronecker.hh:233
FieldType operator()(Dims... indices) const
Compare the provided indices with the pivot sequence and return the result of the comparison.
Definition: kronecker.hh:56
decltype(auto) operator()(Seq< Indices... >) const
Constant access from index-sequence.
Definition: kronecker.hh:70
constexpr decltype(auto) expressionClosure(T &&t)
Do-nothing default implementation for pathologic cases.
Definition: interface.hh:93
decltype(operate(std::declval< OptOrF >(), std::declval< Rest >()...)) ExpressionType
Generate the type of an expression by calling operate().
Definition: optimizationbase.hh:256
constexpr std::size_t WeightV
Provide an overridable weight for expressions which defaults to their depth.
Definition: weight.hh:14
BoolConstant< ExpressionTraits< T >::isTypedValue > IsTypedValue
Compile-time true if T is a "typed value", e.g. a std::integral_constant.
Definition: expressiontraits.hh:90
auto & assign(T1 &t1, T2 &&t2)
Assign one tuple-alike to another by looping over the elements.
Definition: assign.hh:40
typename GetHeadPartHelper< Cnt, Seq >::Type HeadPart
Extract Cnt many consecutive elements from the front of Seq.
Definition: access.hh:217
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
decltype(isIntegralTuple(std::declval< T >())) IsIntegralTuple
Decide whether the given tuple contains only integral types.
Definition: compare.hh:402
constexpr bool isConstant(Sequence< T, T0, Ts... >)
Definition: compare.hh:285
decltype(isIntegralPack(std::declval< T >()...)) IsIntegralPack
Decide whether the given parameter pack contains only integral types.
Definition: compare.hh:377
Constant< bool, V > BoolConstant
Short-cut for integral constant of type bool.
Definition: types.hh:48
BoolConstant< false > FalseType
Alias for std::false_type.
Definition: types.hh:110
BoolConstant< true > TrueType
Alias for std::true_type.
Definition: types.hh:107
A constant.
Definition: tags.hh:93
Terminals may derive from this class to express that they are expressions.
Definition: terminal.hh:25
Gets the type of the n-th element of a tuple-like or the std::integral_constant corresponding to the ...
Definition: access.hh:42
Definition: types.hh:374
Traits in order to identify a Projection class.
Definition: kronecker.hh:251
Base class for all tensors.
Definition: tensorbase.hh:144
A terminal expression is an "expression end-point", i.e.
Definition: tags.hh:48
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)