SPH
SymmetricTensor.h
Go to the documentation of this file.
1 #pragma once
2 
7 
8 #include "math/AffineMatrix.h"
10 
12 
13 struct Svd;
14 
19 private:
20  Vector diag; // diagonal part
21  Vector off; // over/below diagonal
22 
23 public:
24  SymmetricTensor() = default;
25 
27  : diag(other.diag)
28  , off(other.off) {}
29 
32  INLINE SymmetricTensor(const Vector& diag, const Vector& off)
33  : diag(diag)
34  , off(off) {}
35 
37  INLINE explicit SymmetricTensor(const Float value)
38  : diag(value)
39  , off(value) {}
40 
44  INLINE SymmetricTensor(const Vector& v0, const Vector& v1, const Vector& v2) {
45  SPH_ASSERT(v0[1] == v1[0], v0[1], v1[0]);
46  SPH_ASSERT(v0[2] == v2[0], v0[2], v2[0]);
47  SPH_ASSERT(v1[2] == v2[1], v1[2], v2[1]);
48  diag = Vector(v0[0], v1[1], v2[2]);
49  off = Vector(v0[1], v0[2], v1[2]);
50  }
51 
53  diag = other.diag;
54  off = other.off;
55  return *this;
56  }
57 
59  INLINE Vector row(const Size idx) const {
60  SPH_ASSERT(idx < 3);
61  switch (idx) {
62  case 0:
63  return Vector(diag[0], off[0], off[1]);
64  case 1:
65  return Vector(off[0], diag[1], off[2]);
66  case 2:
67  return Vector(off[1], off[2], diag[2]);
68  default:
69  STOP;
70  }
71  }
72 
74  INLINE Float& operator()(const Size rowIdx, const Size colIdx) {
75  if (rowIdx == colIdx) {
76  return diag[rowIdx];
77  } else {
78  return off[rowIdx + colIdx - 1];
79  }
80  }
81 
83  INLINE Float operator()(const Size rowIdx, const Size colIdx) const {
84  if (rowIdx == colIdx) {
85  return diag[rowIdx];
86  } else {
87  return off[rowIdx + colIdx - 1];
88  }
89  }
90 
92  INLINE const Vector& diagonal() const {
93  return diag;
94  }
95 
97  INLINE const Vector& offDiagonal() const {
98  return off;
99  }
100 
102  INLINE Vector operator*(const Vector& v) const {
104  return Vector(diag[0] * v[0] + off[0] * v[1] + off[1] * v[2],
105  off[0] * v[0] + diag[1] * v[1] + off[2] * v[2],
106  off[1] * v[0] + off[2] * v[1] + diag[2] * v[2]);
107  }
108 
111  return SymmetricTensor(t.diag * v, t.off * v);
112  }
113 
115  return SymmetricTensor(t.diag * v, t.off * v);
116  }
117 
120  return SymmetricTensor(t1.diag * t2.diag, t1.off * t2.off);
121  }
122 
125  return SymmetricTensor(t.diag / v, t.off / v);
126  }
127 
130  return SymmetricTensor(t1.diag / t2.diag, t1.off / t2.off);
131  }
132 
135  return SymmetricTensor(t1.diag + t2.diag, t1.off + t2.off);
136  }
137 
139  return SymmetricTensor(t1.diag - t2.diag, t1.off - t2.off);
140  }
141 
143  diag += other.diag;
144  off += other.off;
145  return *this;
146  }
147 
149  diag -= other.diag;
150  off -= other.off;
151  return *this;
152  }
153 
155  diag *= value;
156  off *= value;
157  return *this;
158  }
159 
161  diag /= value;
162  off /= value;
163  return *this;
164  }
165 
167  return SymmetricTensor(-diag, -off);
168  }
169 
170  /* INLINE explicit operator Tensor() const {
171  return Tensor((*this)[0], (*this)[1], (*this)[2]);
172  }*/
173 
174  INLINE bool operator==(const SymmetricTensor& other) const {
175  return diag == other.diag && off == other.off;
176  }
177 
178  INLINE bool operator!=(const SymmetricTensor& other) const {
179  return diag != other.diag || off != other.off;
180  }
181 
184  return SymmetricTensor(Vector(1._f, 1._f, 1._f), Vector(0._f, 0._f, 0._f));
185  }
186 
188  INLINE static SymmetricTensor null() {
189  return SymmetricTensor(Vector(0._f), Vector(0._f));
190  }
191 
194  return diag[0] * diag[1] * diag[2] + 2 * off[0] * off[1] * off[2] -
195  (dot(sqr(off), Vector(diag[2], diag[1], diag[0])));
196  }
197 
199  INLINE Float trace() const {
200  return dot(diag, Vector(1._f));
201  }
202 
204  template <int n>
206  switch (n) {
207  case 1:
208  return trace();
209  case 2:
211  return getSqrLength(off) - (diag[1] * diag[2] + diag[2] * diag[0] + diag[0] * diag[1]);
212  case 3:
213  return determinant();
214  default:
215  STOP;
216  }
217  }
218 
220  const Float det = determinant();
221  SPH_ASSERT(det != 0._f);
222  Vector invDiag, invOff;
224  invDiag[0] = diag[1] * diag[2] - sqr(off[2]);
225  invDiag[1] = diag[2] * diag[0] - sqr(off[1]);
226  invDiag[2] = diag[0] * diag[1] - sqr(off[0]);
227  invOff[0] = off[1] * off[2] - diag[2] * off[0];
228  invOff[1] = off[2] * off[0] - diag[1] * off[1];
229  invOff[2] = off[0] * off[1] - diag[0] * off[2];
230  return SymmetricTensor(invDiag / det, invOff / det);
231  }
232 
233  // Moore-Penrose pseudo-inversion of matrix
234  SymmetricTensor pseudoInverse(const Float eps) const;
235 
236  friend std::ostream& operator<<(std::ostream& stream, const SymmetricTensor& t) {
237  stream << t.diagonal() << t.offDiagonal();
238  return stream;
239  }
240 };
241 
245  const AffineMatrix m(t.row(0), t.row(1), t.row(2));
246  AffineMatrix transformed = transform * m * transform.inverse();
247  return SymmetricTensor(Vector(transformed(0, 0), transformed(1, 1), transformed(2, 2)),
248  0.5_f * Vector(transformed(0, 1) + transformed(1, 0),
249  transformed(0, 2) + transformed(2, 0),
250  transformed(1, 2) + transformed(2, 1)));
251 }
252 
253 template <typename T1, typename T2>
254 T1 convert(const T2& matrix);
255 
256 template <>
258  SPH_ASSERT(almostEqual(matrix(0, 1), matrix(1, 0), 1.e-6_f) &&
259  almostEqual(matrix(0, 2), matrix(2, 0), 1.e-6_f) &&
260  almostEqual(matrix(1, 2), matrix(2, 1), 1.e-6_f));
261  return SymmetricTensor(
262  Vector(matrix(0, 0), matrix(1, 1), matrix(2, 2)), Vector(matrix(0, 1), matrix(0, 2), matrix(1, 2)));
263 }
264 
265 template <>
267  // make sure there is no 'accidental' translation in the matrix
268  SPH_ASSERT(t.row(0)[H] == 0._f);
269  SPH_ASSERT(t.row(1)[H] == 0._f);
270  SPH_ASSERT(t.row(2)[H] == 0._f);
271  return AffineMatrix(t.row(0), t.row(1), t.row(2));
272 }
273 
274 
276 
277 
279 INLINE bool almostEqual(const SymmetricTensor& t1, const SymmetricTensor& t2, const Float eps = EPS) {
280  return almostEqual(t1.diagonal(), t2.diagonal(), eps) &&
281  almostEqual(t1.offDiagonal(), t2.offDiagonal(), eps);
282 }
283 
288 template <>
290  const Vector v = max(t.diagonal(), t.offDiagonal());
291  SPH_ASSERT(isReal(v));
292  return norm(v);
293 }
294 
296 template <>
298  const Vector v = max(t.diagonal(), t.offDiagonal());
299  return normSqr(v);
300 }
301 
303 template <>
304 INLINE auto abs(const SymmetricTensor& t) {
305  return SymmetricTensor(abs(t.diagonal()), abs(t.offDiagonal()));
306 }
307 
309 template <>
311  return min(minElement(t.diagonal()), minElement(t.offDiagonal()));
312 }
313 
315 template <>
317  return max(maxElement(t.diagonal()), maxElement(t.offDiagonal()));
318 }
319 
321 template <>
323  return SymmetricTensor(min(t1.diagonal(), t2.diagonal()), min(t1.offDiagonal(), t2.offDiagonal()));
324 }
325 
327 template <>
329  return SymmetricTensor(max(t1.diagonal(), t2.diagonal()), max(t1.offDiagonal(), t2.offDiagonal()));
330 }
331 
333 template <>
335  return SymmetricTensor(clamp(t.diagonal(), range), clamp(t.offDiagonal(), range));
336 }
337 
338 template <>
339 INLINE bool isReal(const SymmetricTensor& t) {
340  return isReal(t.diagonal()) && isReal(t.offDiagonal());
341 }
342 
343 template <>
344 INLINE auto less(const SymmetricTensor& t1, const SymmetricTensor& t2) {
345  return SymmetricTensor(less(t1.diagonal(), t2.diagonal()), less(t1.offDiagonal(), t2.offDiagonal()));
346 }
347 
348 template <>
350  return { t(0, 0), t(1, 1), t(2, 2), t(0, 1), t(0, 2), t(1, 2) };
351 }
352 
355  return dot(t1.diagonal(), t2.diagonal()) + 2._f * dot(t1.offDiagonal(), t2.offDiagonal());
356 }
357 
363  return SymmetricTensor(v1 * v2,
364  0.5_f * Vector(v1[0] * v2[1] + v1[1] * v2[0],
365  v1[0] * v2[2] + v1[2] * v2[0],
366  v1[1] * v2[2] + v1[2] * v2[1]));
367 }
368 
371  const Float n = norm(t);
372  if (n < 1.e-12_f) {
373  return { 0._f, 0._f, 0._f };
374  }
375  const Float p = -t.invariant<1>() / n;
376  const Float q = -t.invariant<2>() / sqr(n);
377  const Float r = -t.invariant<3>() / pow<3>(n);
378 
379  const Float a = q - p * p / 3._f;
380  const Float b = (2._f * pow<3>(p) - 9._f * p * q + 27._f * r) / 27._f;
381  const Float aCub = pow<3>(a) / 27._f;
382  if (0.25_f * b * b + aCub >= 0._f) {
383  return { 0._f, 0._f, 0._f };
384  }
385  SPH_ASSERT(a < 0._f);
386  const Float t1 = 2._f * sqrt(-a / 3._f);
387  const Float phi = acos(-0.5_f * b / sqrt(-aCub));
388  const Vector v(phi / 3._f, (phi + 2 * PI) / 3._f, (phi + 4 * PI) / 3._f);
389  const Vector sig = t1 * cos(v) - Vector(p / 3._f);
390  return { sig[0] * n, sig[1] * n, sig[2] * n };
391 }
392 
393 struct Eigen {
396 
399 };
400 
403 
404 struct Svd {
408 };
409 
412 
Three-dimensional affine matrix.
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
#define STOP
Definition: Assert.h:106
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
constexpr Float EPS
Definition: MathUtils.h:30
constexpr INLINE T sqr(const T &f) noexcept
Return a squared value.
Definition: MathUtils.h:67
INLINE T cos(const T f)
Definition: MathUtils.h:291
INLINE T sqrt(const T f)
Return a squared root of a value.
Definition: MathUtils.h:78
constexpr INLINE Float pow< 3 >(const Float v)
Definition: MathUtils.h:132
INLINE T acos(const T f)
Definition: MathUtils.h:306
constexpr Float PI
Mathematical constants.
Definition: MathUtils.h:361
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
INLINE SymmetricTensor symmetricOuter(const Vector &v1, const Vector &v2)
SYMMETRIZED outer product of two vectors.
Eigen eigenDecomposition(const SymmetricTensor &t)
Computes eigenvectors and corresponding eigenvalues of symmetric matrix.
INLINE auto less(const SymmetricTensor &t1, const SymmetricTensor &t2)
INLINE SymmetricTensor max(const SymmetricTensor &t1, const SymmetricTensor &t2)
Component-wise maximum of two tensors.
INLINE SymmetricTensor clamp(const SymmetricTensor &t, const Interval &range)
Clamping all components by range.
INLINE bool isReal(const SymmetricTensor &t)
INLINE SymmetricTensor transform(const SymmetricTensor &t, const AffineMatrix &transform)
INLINE StaticArray< Float, 6 > getComponents(const SymmetricTensor &t)
INLINE Float norm(const SymmetricTensor &t)
INLINE Float minElement(const SymmetricTensor &t)
Returns the minimal element of the tensor.
T1 convert(const T2 &matrix)
INLINE auto abs(const SymmetricTensor &t)
Returns the tensor of absolute values.
INLINE bool almostEqual(const SymmetricTensor &t1, const SymmetricTensor &t2, const Float eps=EPS)
Tensor utils.
INLINE Float normSqr(const SymmetricTensor &t)
Arbitrary squared norm of the tensor.
INLINE StaticArray< Float, 3 > findEigenvalues(const SymmetricTensor &t)
Returns three eigenvalue of symmetric matrix.
INLINE Float maxElement(const SymmetricTensor &t)
Returns the maximal element of the tensor.
Svd singularValueDecomposition(const SymmetricTensor &t)
Computes the singular value decomposition of symmetric matrix.
INLINE Float ddot(const SymmetricTensor &t1, const SymmetricTensor &t2)
Double-dot product t1 : t2 = sum_ij t1_ij t2_ij.
INLINE SymmetricTensor min(const SymmetricTensor &t1, const SymmetricTensor &t2)
Component-wise minimum of two tensors.
INLINE Float getSqrLength(const Vector &v)
Definition: Vector.h:574
BasicVector< Float > Vector
Definition: Vector.h:539
INLINE float dot(const BasicVector< float > &v1, const BasicVector< float > &v2)
Make sure the vector is trivially constructible and destructible, needed for fast initialization of a...
Definition: Vector.h:548
@ H
Definition: Vector.h:25
Object representing a 1D interval of real numbers.
Definition: Interval.h:17
Array with fixed number of allocated elements.
Definition: StaticArray.h:19
Symmetric tensor of 2nd order.
INLINE SymmetricTensor & operator-=(const SymmetricTensor &other)
INLINE Float & operator()(const Size rowIdx, const Size colIdx)
Returns a given element of the matrix.
INLINE const Vector & offDiagonal() const
Returns the off-diagonal elements of the tensor.
INLINE Float operator()(const Size rowIdx, const Size colIdx) const
Returns a given element of the matrix, const version.
INLINE SymmetricTensor(const Vector &v0, const Vector &v1, const Vector &v2)
Construct tensor given three vectors as rows.
INLINE friend SymmetricTensor operator-(const SymmetricTensor &t1, const SymmetricTensor &t2)
INLINE Vector operator*(const Vector &v) const
Applies the tensor on given vector.
INLINE bool operator==(const SymmetricTensor &other) const
SymmetricTensor pseudoInverse(const Float eps) const
INLINE SymmetricTensor operator-() const
INLINE friend SymmetricTensor operator/(const SymmetricTensor &t, const Float v)
Divides a tensor by a scalar.
INLINE SymmetricTensor & operator=(const SymmetricTensor &other)
INLINE SymmetricTensor(const Float value)
Initialize all components of the tensor to given value.
INLINE Float invariant() const
Returns n-th invariant of the tensor (1<=n<=3)
friend std::ostream & operator<<(std::ostream &stream, const SymmetricTensor &t)
INLINE friend SymmetricTensor operator*(const SymmetricTensor &t1, const SymmetricTensor &t2)
Multiplies a tensor by another tensor, element-wise. Not a matrix multiplication!
INLINE SymmetricTensor(const Vector &diag, const Vector &off)
Construct tensor given its diagonal vector and a vector of off-diagonal elements (sorted top-bottom a...
INLINE bool operator!=(const SymmetricTensor &other) const
INLINE SymmetricTensor(const SymmetricTensor &other)
INLINE Float trace() const
Return the trace of the tensor.
INLINE friend SymmetricTensor operator*(const Float v, const SymmetricTensor &t)
INLINE SymmetricTensor inverse() const
INLINE friend SymmetricTensor operator*(const SymmetricTensor &t, const Float v)
Multiplies a tensor by a scalar.
INLINE Vector row(const Size idx) const
Returns a row of the matrix.
static INLINE SymmetricTensor identity()
Returns an identity tensor.
INLINE friend SymmetricTensor operator+(const SymmetricTensor &t1, const SymmetricTensor &t2)
Sums up two tensors.
SymmetricTensor()=default
INLINE friend SymmetricTensor operator/(const SymmetricTensor &t1, const SymmetricTensor &t2)
Divides a tensor by another tensor, element-wise.
INLINE Float determinant() const
Returns the determinant of the tensor.
INLINE SymmetricTensor & operator+=(const SymmetricTensor &other)
INLINE SymmetricTensor & operator/=(const Float value)
INLINE SymmetricTensor & operator*=(const Float value)
INLINE const Vector & diagonal() const
Returns the diagonal part of the tensor.
AffineMatrix vectors
Matrix of eigenvectors, stored as rows.
Vector values
Eigenvalues.
AffineMatrix U
Vector S
AffineMatrix V