1#ifndef __DUNE_ACFEM_TENSORS_MODULES_KRONECKER_HH__
2#define __DUNE_ACFEM_TENSORS_MODULES_KRONECKER_HH__
4#include "../../mpl/assign.hh"
5#include "../tensorbase.hh"
6#include "../expressiontraits.hh"
22 template<
class Signature,
class PivotIndices,
class Field>
25 template<
class Signature,
class PivotIndices,
class Field>
26 struct HasSpecializedExpressionTraits<KroneckerDelta<Signature, PivotIndices, Field> >
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> >
37 ,
public MPL::UniqueTags<ConstantExpression,
38 ConditionalType<IsTypedValue<Field>::value, TypedValueExpression, void> >
43 using typename BaseType::Signature;
44 using typename BaseType::FieldType;
45 using PivotSequence = Seq<PivotIndices...>;
46 using ValueType = Field;
51 template<
class... Dims,
52 std::enable_if_t<(
sizeof...(Dims) == rank
58 if (std::make_tuple((std::size_t)indices...) != std::make_tuple(PivotIndices...)) {
61 return FieldType(ValueType{});
68 template<std::size_t... Indices,
69 std::enable_if_t<
sizeof...(Indices) == rank,
int> = 0>
72 using ReturnType = ConditionalType<isZero<Indices...>(),
81 template<std::size_t... Indices, std::size_t... Pos>
82 static bool constexpr isZeroExpander(Seq<Indices...>, Seq<Pos...>)
84 return !(... && (Indices ==
Get<Pos, Seq<PivotIndices...> >::value));
88 template<std::size_t... Indices,
class Pos =
MakeIndexSequence<
sizeof...(Indices)> >
89 static bool constexpr isZero(Seq<Indices...> = Seq<Indices...>{}, Pos = Pos{})
92 using RealPos =
HeadPart<
sizeof...(Indices), Pos>;
94 return isZeroExpander(Seq<Indices...>{}, RealPos{});
97 std::string name()
const
99 return "delta<"+toString(Signature{})+
"@["+toString(PivotSequence{})+
"]>";
102 static constexpr auto lookAt()
104 return PivotSequence{};
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> >
119 using BaseType::rank;
120 using typename BaseType::Signature;
121 using typename BaseType::FieldType;
122 using ValueType = Field;
126 template<std::size_t... I,
class T>
127 KroneckerDelta(T&& tuple, Seq<I...>&&)
128 : pivotIndices_({{ (std::size_t)std::get<I>(tuple)... }})
156 template<
class... Indices,
157 std::enable_if_t<(
sizeof...(Indices) != 0
159 sizeof...(Indices) == rank
164 : pivotIndices_({{ (std::size_t)indices... }})
170 template<
class... Dims,
171 std::enable_if_t<(
sizeof...(Dims) == rank
177 if (std::array<std::size_t, rank>({{ (std::size_t)indices... }}) != pivotIndices_) {
180 return FieldType(ValueType{});
189 template<std::size_t... Indices,
190 std::enable_if_t<
sizeof...(Indices) == rank,
int> = 0>
193 return (*
this)(Indices...);
196 template<std::size_t... Indices,
class Pos =
MakeIndexSequence<
sizeof...(Indices)> >
197 static bool constexpr isZero(Seq<Indices...> = Seq<Indices...>{}, Pos = Pos{})
206 template<
class... Indices,
207 std::enable_if_t<((
sizeof...(Indices) > 0)
212 static_assert(
sizeof...(Indices) == rank,
213 "The number of pivot indices must match the co-dimension.");
214 pivotIndices_ = {{ (std::size_t)indices... }};
227 static_assert(size<T>() == rank,
228 "The number of pivot indices must match the co-dimension.");
233 const std::array<std::size_t, rank>&
lookAt() const&
235 return pivotIndices_;
238 std::string name()
const
240 return "delta<"+toString(Signature{})+
"@["+toString(pivotIndices_)+
"]>";
244 std::array<std::size_t, rank> pivotIndices_;
248 template<
class T,
class SFINAE =
void>
258 template<std::size_t... Pos,
class PivotIndices,
class Field>
259 struct IsKroneckerDelta<KroneckerDelta<Seq<Pos...>, PivotIndices, Field> >
264 struct IsConstKroneckerDelta
269 struct IsConstKroneckerDelta<T&>
270 : IsConstKroneckerDelta<std::decay_t<T> >
274 struct IsConstKroneckerDelta<T&&>
275 : IsConstKroneckerDelta<std::decay_t<T> >
281 template<std::size_t... Pos, std::size_t... Pivot,
class Field>
282 struct IsConstKroneckerDelta<KroneckerDelta<Seq<Pos...>, Seq<Pivot...>, Field> >
287 struct IsDiagonalKroneckerDelta
292 struct IsDiagonalKroneckerDelta<T&>
293 : IsDiagonalKroneckerDelta<T>
297 struct IsDiagonalKroneckerDelta<T&&>
298 : IsDiagonalKroneckerDelta<T>
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> >
307 using PivotSequence =
typename std::decay_t<T>::PivotSequence;
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{})
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");
318 return closure(KroneckerDelta<Dims, Seq<Index...>, IntFraction<1> >{});
321 template<std::size_t... Dimensions, std::size_t... Index,
class F = Expressions::Closure>
322 auto kroneckerDelta(Seq<Dimensions...>, Seq<Index...>, F closure = F{})
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");
329 return closure(KroneckerDelta<Seq<Dimensions...>, Seq<Index...>, IntFraction<1> >{});
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{})
336 return kroneckerDelta(
typename TensorTraits<T>::Signature{}, Seq<Index...>{}, F{});
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{})
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));
348 template<std::size_t... Dimensions,
class... Indices,
350 auto kroneckerDelta(Seq<Dimensions...>, Indices... indices)
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...));
363 using Tensor::kroneckerDelta;
365 template<
class Field,
class Signature,
class Indices>
366 struct ExpressionTraits<Tensor::KroneckerDelta<Signature, Indices, Field> >
367 : ExpressionTraits<Field>
370 using BaseType = ExpressionTraits<Field>;
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>;
381 static constexpr bool isIndependent = BaseType::isIndependent;
383 static constexpr bool isTypedValue = BaseType::isTypedValue && !std::is_same<Indices, Tensor::Seq<> >::value;
386 namespace Expressions {
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));
395 template<
class Field,
class Signature,
class Indices>
396 struct FieldTraits<ACFem::Tensor::KroneckerDelta<Signature, Indices, Field> >
397 : FieldTraits<std::decay_t<Field> >
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
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