SPH
TracelessTensor.h
Go to the documentation of this file.
1 #pragma once
2 
7 
9 
11 
17  template <typename T>
18  friend Float minElement(const T& t);
19  template <typename T>
20  friend Float maxElement(const T& t);
21  template <typename T>
22  friend auto abs(const T& t);
23  template <typename T>
24  friend T sqrtInv(const T& t);
25  template <typename T>
26  friend constexpr T min(const T& t1, const T& t2);
27  template <typename T>
28  friend constexpr T max(const T& t1, const T& t2);
29  template <typename T>
30  friend T clamp(const T& t, const Interval& range);
31  template <typename T>
32  friend constexpr auto less(const T& t1, const T& t2);
33 
34 private:
35  // 5 independent components: 4 in vector, 1 in float
36  enum Ids {
37  M00,
38  M11,
39  M01,
40  M02 // order of components in vector
41  };
42 
44  Vector m;
45  Float m12;
46 
47  INLINE TracelessTensor(const Vector& m, const Float m12)
48  : m(m)
49  , m12(m12) {}
50 
51 public:
52  INLINE TracelessTensor() = default;
53 
54  INLINE TracelessTensor(const TracelessTensor& other) = default;
55 
59  INLINE explicit TracelessTensor(const SymmetricTensor& other) {
60  m = other.diagonal();
61  const Vector& off = other.offDiagonal();
62  m[M01] = off[0];
63  m[M02] = off[1];
64  m12 = off[2];
65  // assert after we set variables to shut up gcc's "maybe uninitialized" warning
66  SPH_ASSERT(abs(other.trace()) <= 1.e-3_f * getLength(other.diagonal()) + EPS, *this, other);
67  }
68 
73  INLINE explicit TracelessTensor(const Float value)
74  : m(value)
75  , m12(value) {}
76 
78  INLINE TracelessTensor(const Float xx, const Float yy, const Float xy, const Float xz, const Float yz)
79  : m(xx, yy, xy, xz)
80  , m12(yz) {}
81 
85  INLINE TracelessTensor(const Vector& v0, const Vector& v1, const Vector& v2) {
86  SPH_ASSERT(v0[1] == v1[0]);
87  SPH_ASSERT(v0[2] == v2[0]);
88  SPH_ASSERT(v1[2] == v2[1]);
89  SPH_ASSERT(abs(v0[0] + v1[1] + v2[2]) < EPS * (norm(v0) + norm(v1) + norm(v2)));
90  m = Vector(v0[0], v1[1], v0[1], v0[2]);
91  m12 = v1[2];
92  }
93 
95  m = other.m;
96  m12 = other.m12;
97  return *this;
98  }
99 
101  *this = TracelessTensor(other);
102  return *this;
103  }
104 
106  INLINE explicit operator SymmetricTensor() const {
107  return SymmetricTensor(Vector(m[M00], m[M11], -m[M00] - m[M11]), Vector(m[M01], m[M02], m12));
108  }
109 
111  INLINE Vector row(const int idx) const {
112  SPH_ASSERT(unsigned(idx) < 3);
113  switch (idx) {
114  case 0:
115  return Vector(m[M00], m[M01], m[M02]);
116  case 1:
117  return Vector(m[M01], m[M11], m12);
118  case 2:
119  return Vector(m[M02], m12, -m[M00] - m[M11]);
120  default:
121  STOP;
122  }
123  }
124 
127  return Vector(m[M00], m[M11], -m[M00] - m[M11]);
128  }
129 
132  return Vector(m[M01], m[M02], m12);
133  }
134 
139  INLINE Float operator()(const int rowIdx, const int colIdx) const {
140  if (rowIdx == colIdx) {
141  // diagonal
142  if (rowIdx < 2) {
143  return m[rowIdx];
144  } else {
145  return -m[0] - m[1];
146  }
147  } else {
148  // off-diagonal
149  const int sum = rowIdx + colIdx;
150  if (sum < 3) {
151  return m[sum + 1];
152  } else {
153  return m12;
154  }
155  }
156  }
157 
159  INLINE Vector operator*(const Vector& v) const {
160  return Vector(m[M00] * v[0] + m[M01] * v[1] + m[M02] * v[2],
161  m[M01] * v[0] + m[M11] * v[1] + m12 * v[2],
162  m[M02] * v[0] + m12 * v[1] + (-m[M00] - m[M11]) * v[2]);
163  }
164 
167  return TracelessTensor(t.m * v, t.m12 * v);
168  }
169 
171  return TracelessTensor(t.m * v, t.m12 * v);
172  }
173 
176  return TracelessTensor(t.m / v, t.m12 / v);
177  }
178 
180 
181 
183  return TracelessTensor(t1.m + t2.m, t1.m12 + t2.m12);
184  }
185 
187  return TracelessTensor(t1.m - t2.m, t1.m12 - t2.m12);
188  }
189 
191  m += other.m;
192  m12 += other.m12;
193  return *this;
194  }
195 
197  m -= other.m;
198  m12 -= other.m12;
199  return *this;
200  }
201 
203  m *= value;
204  m12 *= value;
205  return *this;
206  }
207 
209  m /= value;
210  m12 /= value;
211  return *this;
212  }
213 
215  return TracelessTensor(-m, -m12);
216  }
217 
218  INLINE bool operator==(const TracelessTensor& other) const {
219  return m == other.m && m12 == other.m12;
220  }
221 
222  INLINE friend bool operator==(const TracelessTensor& t1, const SymmetricTensor& t2) {
223  return t1.diagonal() == t2.diagonal() && t1.offDiagonal() == t2.offDiagonal();
224  }
225 
226  INLINE friend bool operator==(const SymmetricTensor& t1, const TracelessTensor& t2) {
227  return t1.diagonal() == t2.diagonal() && t1.offDiagonal() == t2.offDiagonal();
228  }
229 
230  INLINE bool operator!=(const TracelessTensor& other) const {
231  return m != other.m || m12 != other.m12;
232  }
233 
234  INLINE friend bool operator!=(const TracelessTensor& t1, const SymmetricTensor& t2) {
235  return t1.diagonal() != t2.diagonal() || t1.offDiagonal() != t2.offDiagonal();
236  }
237 
238  INLINE friend bool operator!=(const SymmetricTensor& t1, const TracelessTensor& t2) {
239  return t1.diagonal() != t2.diagonal() || t1.offDiagonal() != t2.offDiagonal();
240  }
241 
243  INLINE static TracelessTensor null() {
244  return TracelessTensor(0._f);
245  }
246 
247  friend std::ostream& operator<<(std::ostream& stream, const TracelessTensor& t) {
248  stream << std::setprecision(6) << std::setw(20) << t(0, 0) << std::setw(20) << t(1, 1)
249  << std::setw(20) << t(0, 1) << std::setw(20) << t(0, 2) << std::setw(20) << t(1, 2);
250  return stream;
251  }
252 };
253 
254 template <>
256  SPH_ASSERT(almostEqual(m(0, 1), m(1, 0), 1.e-6_f) && almostEqual(m(0, 2), m(2, 0), 1.e-6_f) &&
257  almostEqual(m(1, 2), m(2, 1), 1.e-6_f));
258  SPH_ASSERT(almostEqual(m(0, 0) + m(1, 1) + m(2, 2), 0._f, 1.e-6_f));
259  return TracelessTensor(m(0, 0), m(1, 1), m(0, 1), m(0, 2), m(1, 2));
260 }
261 
262 template <>
264  // make sure there is no 'accidental' translation in the matrix
265  SPH_ASSERT(t.row(0)[H] == 0._f);
266  SPH_ASSERT(t.row(1)[H] == 0._f);
267  SPH_ASSERT(t.row(2)[H] == 0._f);
268  return AffineMatrix(t.row(0), t.row(1), t.row(2));
269 }
270 
272 INLINE bool almostEqual(const TracelessTensor& t1, const TracelessTensor& t2, const Float eps = EPS) {
273  return almostEqual(t1.diagonal(), t2.diagonal(), eps) &&
274  almostEqual(t1.offDiagonal(), t2.offDiagonal(), eps);
275 }
276 
279 template <>
282  const Vector v = max(t.diagonal(), t.offDiagonal());
283  SPH_ASSERT(isReal(v));
284  return norm(v);
285 }
286 
288 template <>
290  const Vector v = max(t.diagonal(), t.offDiagonal());
291  SPH_ASSERT(isReal(v));
292  return normSqr(v);
293 }
294 
296 template <>
299  const Float vectorMin = min(min(t.m[0], t.m[1]), min(t.m[2], t.m[3]));
300  const Float result = min(vectorMin, t.m12, -t.m[0] - t.m[1]);
301  SPH_ASSERT(isReal(result) && result <= 0._f);
302  return result;
303 }
304 
306 template <>
309  const Float vectorMax = max(max(t.m[0], t.m[1]), max(t.m[2], t.m[3]));
310  const Float result = max(vectorMax, t.m12, -t.m[0] - t.m[1]);
311  SPH_ASSERT(isReal(result) && result >= 0._f);
312  return result;
313 }
314 
315 
319 template <>
320 INLINE auto abs(const TracelessTensor& t) {
321  return SymmetricTensor(abs(t.diagonal()), abs(t.offDiagonal()));
322 }
323 
324 template <>
327 }
328 
330 template <>
332  return TracelessTensor(min(t1.m, t2.m), min(t1.m12, t2.m12));
333 }
334 
336 template <>
338  return TracelessTensor(max(t1.m, t2.m), max(t1.m12, t2.m12));
339 }
340 
341 
342 template <>
343 INLINE auto less(const TracelessTensor& t1, const TracelessTensor& t2) {
344  return SymmetricTensor(less(t1.diagonal(), t2.diagonal()), less(t1.offDiagonal(), t2.offDiagonal()));
345 }
346 
353 template <>
355  const SymmetricTensor clamped(clamp(t.diagonal(), range), clamp(t.offDiagonal(), range));
356  return TracelessTensor(clamped - SymmetricTensor::identity() * clamped.trace() / 3._f);
357 }
358 
359 template <>
361  const TracelessTensor& dv,
362  const Interval& range) {
363  const SymmetricTensor lower = less(SymmetricTensor(range.lower()), SymmetricTensor(v));
364  const SymmetricTensor upper = less(SymmetricTensor(v), SymmetricTensor(range.upper()));
366  return { clamp(v, range), TracelessTensor(SymmetricTensor(dv) * lower * upper) };
367 }
368 
369 template <>
370 INLINE bool isReal(const TracelessTensor& t) {
371  return isReal(t.diagonal()) && isReal(t.offDiagonal());
372 }
373 
376  return dot(t1.diagonal(), t2.diagonal()) + 2._f * dot(t1.offDiagonal(), t2.offDiagonal());
377 }
378 
380  return dot(t1.diagonal(), t2.diagonal()) + 2._f * dot(t1.offDiagonal(), t2.offDiagonal());
381 }
382 
384  return dot(t1.diagonal(), t2.diagonal()) + 2._f * dot(t1.offDiagonal(), t2.offDiagonal());
385 }
386 
387 template <>
389  return { t(0, 0), t(1, 1), t(2, 2), t(0, 1), t(0, 2), t(1, 2) };
390 }
391 
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
#define STOP
Definition: Assert.h:106
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
Definition: Assert.h:100
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
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
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
Basic algebra for symmetric 2nd order tensors.
INLINE Pair< TracelessTensor > clampWithDerivative(const TracelessTensor &v, const TracelessTensor &dv, const Interval &range)
INLINE bool isReal(const TracelessTensor &t)
INLINE TracelessTensor sqrtInv(const TracelessTensor &)
INLINE TracelessTensor clamp(const TracelessTensor &t, const Interval &range)
Clamps components of the traceless tensor.
INLINE TracelessTensor convert(const AffineMatrix &m)
INLINE Float maxElement(const TracelessTensor &t)
Returns the maximal component of the traceless tensor.
INLINE Float norm(const TracelessTensor &t)
Arbitrary norm of the tensor.
INLINE Float normSqr(const TracelessTensor &t)
Arbitrary squared norm of the tensor.
INLINE Float ddot(const TracelessTensor &t1, const SymmetricTensor &t2)
Double-dot product t1 : t2 = sum_ij t1_ij t2_ij.
INLINE auto abs(const TracelessTensor &t)
Returns the tensor of absolute values form traceless tensor elements.
INLINE TracelessTensor max(const TracelessTensor &t1, const TracelessTensor &t2)
Component-wise maximum of two tensors.
INLINE Float minElement(const TracelessTensor &t)
Returns the minimal component of the traceless tensor.
INLINE auto less(const TracelessTensor &t1, const TracelessTensor &t2)
INLINE StaticArray< Float, 6 > getComponents(const TracelessTensor &t)
INLINE bool almostEqual(const TracelessTensor &t1, const TracelessTensor &t2, const Float eps=EPS)
Checks if two tensors are equal to some given accuracy.
INLINE TracelessTensor min(const TracelessTensor &t1, const TracelessTensor &t2)
Component-wise minimum of two tensors.
INLINE Float getLength(const Vector &v)
Returns the length of the vector. Enabled only for vectors of floating-point precision.
Definition: Vector.h:579
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
INLINE Float lower() const
Returns lower bound of the interval.
Definition: Interval.h:74
INLINE Float upper() const
Returns upper bound of the interval.
Definition: Interval.h:79
Array with fixed number of allocated elements.
Definition: StaticArray.h:19
Symmetric tensor of 2nd order.
INLINE const Vector & offDiagonal() const
Returns the off-diagonal elements of the tensor.
INLINE Float trace() const
Return the trace of the tensor.
static INLINE SymmetricTensor identity()
Returns an identity tensor.
INLINE const Vector & diagonal() const
Returns the diagonal part of the tensor.
Symmetric traceless 2nd order tensor.
INLINE TracelessTensor & operator=(const SymmetricTensor &other)
constexpr friend T min(const T &t1, const T &t2)
Minimum & Maximum value.
Definition: MathBasic.h:15
constexpr friend T max(const T &t1, const T &t2)
Definition: MathBasic.h:20
INLINE Vector row(const int idx) const
Returns a row of the matrix.
friend Float maxElement(const T &t)
Returns maximum element, simply the value iself by default.
Definition: Generic.h:29
friend std::ostream & operator<<(std::ostream &stream, const TracelessTensor &t)
INLINE TracelessTensor operator-() const
INLINE TracelessTensor & operator/=(const Float value)
INLINE TracelessTensor & operator=(const TracelessTensor &other)
friend T sqrtInv(const T &t)
Definition: MathUtils.h:44
INLINE Float operator()(const int rowIdx, const int colIdx) const
Returns a given element of the matrix.
INLINE TracelessTensor(const Float xx, const Float yy, const Float xy, const Float xz, const Float yz)
Initialize tensor given 5 independent components.
INLINE TracelessTensor & operator-=(const TracelessTensor &other)
INLINE friend bool operator==(const SymmetricTensor &t1, const TracelessTensor &t2)
INLINE friend bool operator!=(const SymmetricTensor &t1, const TracelessTensor &t2)
friend auto abs(const T &t)
Definition: MathUtils.h:276
INLINE friend TracelessTensor operator-(const TracelessTensor &t1, const TracelessTensor &t2)
INLINE TracelessTensor & operator*=(const Float value)
INLINE friend TracelessTensor operator*(const Float v, const TracelessTensor &t)
INLINE Vector operator*(const Vector &v) const
Applies the tensor on given vector.
INLINE TracelessTensor(const TracelessTensor &other)=default
INLINE friend TracelessTensor operator*(const TracelessTensor &t, const Float v)
Multiplies the tensor by a scalar.
INLINE TracelessTensor(const SymmetricTensor &other)
Construct traceless tensor using other tensor (not traceless in general).
INLINE Vector offDiagonal() const
Returns off-diagonal elements of the matrix.
INLINE Vector diagonal() const
Returns diagonal of the matrix.
INLINE TracelessTensor(const Float value)
Initialize all components of the tensor to given value, excluding last element of the diagonal,...
friend Float minElement(const T &t)
Returns minimum element, simply the value iself by default.
Definition: Generic.h:37
INLINE friend bool operator!=(const TracelessTensor &t1, const SymmetricTensor &t2)
INLINE bool operator!=(const TracelessTensor &other) const
INLINE friend TracelessTensor operator/(const TracelessTensor &t, const Float v)
Divides a tensor by a scalar.
INLINE friend TracelessTensor operator+(const TracelessTensor &t1, const TracelessTensor &t2)
INLINE TracelessTensor & operator+=(const TracelessTensor &other)
INLINE TracelessTensor(const Vector &v0, const Vector &v1, const Vector &v2)
Construct tensor given three vectors as rows.
INLINE friend bool operator==(const TracelessTensor &t1, const SymmetricTensor &t2)
constexpr friend auto less(const T &t1, const T &t2)
Compares two objects of the same time component-wise.
Definition: Generic.h:53
friend T clamp(const T &t, const Interval &range)
Definition: Interval.h:120
INLINE TracelessTensor()=default
INLINE bool operator==(const TracelessTensor &other) const
constexpr Size sum()
Definition: Multipole.h:31