Physical Quantities  v1.0.0
C++ library of physical quantities, physical models, and units of measure for scientific computing. https://github.com/acodcha/phq
SymmetricDyad.hpp
Go to the documentation of this file.
1 // Copyright © 2020-2024 Alexandre Coderre-Chabot
2 //
3 // This file is part of Physical Quantities (PhQ), a C++ library of physical quantities, physical
4 // models, and units of measure for scientific computing.
5 //
6 // Physical Quantities is hosted at:
7 // https://github.com/acodcha/phq
8 //
9 // Physical Quantities is licensed under the MIT License:
10 // https://mit-license.org
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
13 // associated documentation files (the "Software"), to deal in the Software without restriction,
14 // including without limitation the rights to use, copy, modify, merge, publish, distribute,
15 // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 // - The above copyright notice and this permission notice shall be included in all copies or
18 // substantial portions of the Software.
19 // - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
20 // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 #ifndef PHQ_SYMMETRIC_DYAD_HPP
26 #define PHQ_SYMMETRIC_DYAD_HPP
27 
28 #include <array>
29 #include <cstddef>
30 #include <functional>
31 #include <optional>
32 #include <ostream>
33 #include <string>
34 #include <type_traits>
35 
36 #include "Base.hpp"
37 #include "PlanarVector.hpp"
38 #include "Vector.hpp"
39 
40 namespace PhQ {
41 
42 /// \brief Symmetric three-dimensional Euclidean dyadic tensor. Contains six components in Cartesian
43 /// coordinates: xx, xy = yx, xz = zx, yy, yz = zy, and zz. For the general case of a
44 /// three-dimensional Euclidean dyadic tensor which may be symmetric or asymmetric, see PhQ::Dyad.
45 /// For a three-dimensional Euclidean vector, see PhQ::Vector. For a two-dimensional Euclidean
46 /// vector in the XY plane, see PhQ::PlanarVector.
47 /// \tparam NumericType Floating-point numeric type: float, double, or long double. Defaults to
48 /// double if unspecified.
49 template <typename NumericType = double>
51  static_assert(std::is_floating_point<NumericType>::value,
52  "The NumericType template parameter of PhQ::SymmetricDyad<NumericType> must be a "
53  "numeric floating-point type: float, double, or long double.");
54 
55 public:
56  /// \brief Default constructor. Constructs a three-dimensional symmetric dyadic tensor with
57  /// uninitialized xx, xy, xz, yy, yz, and zz Cartesian components.
58  SymmetricDyad() = default;
59 
60  /// \brief Constructor. Constructs a three-dimensional symmetric dyadic tensor from the given xx,
61  /// xy, xz, yy, yz, and zz Cartesian components.
62  constexpr SymmetricDyad(const NumericType xx, const NumericType xy, const NumericType xz,
63  const NumericType yy, const NumericType yz, const NumericType zz)
64  : xx_xy_xz_yy_yz_zz_({xx, xy, xz, yy, yz, zz}) {}
65 
66  /// \brief Constructor. Constructs a three-dimensional symmetric dyadic tensor from a given array
67  /// representing its xx, xy, xz, yy, yz, and zz Cartesian components.
68  explicit constexpr SymmetricDyad(const std::array<NumericType, 6>& xx_xy_xz_yy_yz_zz)
70 
71  /// \brief Destructor. Destroys this three-dimensional symmetric dyadic tensor.
72  ~SymmetricDyad() noexcept = default;
73 
74  /// \brief Copy constructor. Constructs a three-dimensional symmetric dyadic tensor by copying
75  /// another one.
76  constexpr SymmetricDyad(const SymmetricDyad<NumericType>& other) = default;
77 
78  /// \brief Copy constructor. Constructs a three-dimensional symmetric dyadic tensor by copying
79  /// another one.
80  template <typename OtherNumericType>
81  explicit constexpr SymmetricDyad<NumericType>(const SymmetricDyad<OtherNumericType>& other)
83  {static_cast<NumericType>(other.xx()), static_cast<NumericType>(other.xy()),
84  static_cast<NumericType>(other.xz()), static_cast<NumericType>(other.yy()),
85  static_cast<NumericType>(other.yz()), static_cast<NumericType>(other.zz())}) {}
86 
87  /// \brief Move constructor. Constructs a three-dimensional symmetric dyadic tensor by moving
88  /// another one.
89  constexpr SymmetricDyad<NumericType>(SymmetricDyad<NumericType>&& other) noexcept = default;
90 
91  /// \brief Copy assignment operator. Assigns this three-dimensional symmetric dyadic tensor by
92  /// copying another one.
94  const SymmetricDyad<NumericType>& other) = default;
95 
96  /// \brief Copy assignment operator. Assigns this three-dimensional symmetric dyadic tensor by
97  /// copying another one.
98  template <typename OtherNumericType>
100  xx_xy_xz_yy_yz_zz_[0] = static_cast<NumericType>(other.xx());
101  xx_xy_xz_yy_yz_zz_[1] = static_cast<NumericType>(other.xy());
102  xx_xy_xz_yy_yz_zz_[2] = static_cast<NumericType>(other.xz());
103  xx_xy_xz_yy_yz_zz_[3] = static_cast<NumericType>(other.yy());
104  xx_xy_xz_yy_yz_zz_[4] = static_cast<NumericType>(other.yz());
105  xx_xy_xz_yy_yz_zz_[5] = static_cast<NumericType>(other.zz());
106  return *this;
107  }
108 
109  /// \brief Move assignment operator. Assigns this three-dimensional symmetric dyadic tensor by
110  /// moving another one.
112  SymmetricDyad<NumericType>&& other) noexcept = default;
113 
114  /// \brief Assignment operator. Assigns this three-dimensional symmetric dyadic tensor by copying
115  /// a given array representing its xx, xy, xz, yy, yz, and zz Cartesian components.
117  const std::array<NumericType, 6>& xx_xy_xz_yy_yz_zz) {
119  return *this;
120  }
121 
122  /// \brief Statically creates a three-dimensional symmetric dyadic tensor with its xx, xy, xz, yy,
123  /// yz, and zz Cartesian components initialized to zero.
124  [[nodiscard]] static constexpr SymmetricDyad<NumericType> Zero() {
126  std::array<NumericType, 6>{
127  static_cast<NumericType>(0), static_cast<NumericType>(0), static_cast<NumericType>(0),
128  static_cast<NumericType>(0), static_cast<NumericType>(0), static_cast<NumericType>(0)}
129  };
130  }
131 
132  /// \brief Returns this three-dimensional symmetric dyadic tensor's xx, xy, xz, yy, yz, and zz
133  /// Cartesian components as an array.
134  [[nodiscard]] constexpr const std::array<NumericType, 6>& xx_xy_xz_yy_yz_zz() const noexcept {
135  return xx_xy_xz_yy_yz_zz_;
136  }
137 
138  /// \brief Returns this three-dimensional symmetric dyadic tensor's xx Cartesian component.
139  [[nodiscard]] constexpr NumericType xx() const noexcept {
140  return xx_xy_xz_yy_yz_zz_[0];
141  }
142 
143  /// \brief Returns this three-dimensional symmetric dyadic tensor's xy = yx Cartesian component.
144  [[nodiscard]] constexpr NumericType xy() const noexcept {
145  return xx_xy_xz_yy_yz_zz_[1];
146  }
147 
148  /// \brief Returns this three-dimensional symmetric dyadic tensor's xz = zx Cartesian component.
149  [[nodiscard]] constexpr NumericType xz() const noexcept {
150  return xx_xy_xz_yy_yz_zz_[2];
151  }
152 
153  /// \brief Returns this three-dimensional symmetric dyadic tensor's yx = xy Cartesian component.
154  [[nodiscard]] constexpr NumericType yx() const noexcept {
155  return xx_xy_xz_yy_yz_zz_[1];
156  }
157 
158  /// \brief Returns this three-dimensional symmetric dyadic tensor's yy Cartesian component.
159  [[nodiscard]] constexpr NumericType yy() const noexcept {
160  return xx_xy_xz_yy_yz_zz_[3];
161  }
162 
163  /// \brief Returns this three-dimensional symmetric dyadic tensor's yz = zy Cartesian component.
164  [[nodiscard]] constexpr NumericType yz() const noexcept {
165  return xx_xy_xz_yy_yz_zz_[4];
166  }
167 
168  /// \brief Returns this three-dimensional symmetric dyadic tensor's zx = xz Cartesian component.
169  [[nodiscard]] constexpr NumericType zx() const noexcept {
170  return xx_xy_xz_yy_yz_zz_[2];
171  }
172 
173  /// \brief Returns this three-dimensional symmetric dyadic tensor's zy = yz Cartesian component.
174  [[nodiscard]] constexpr NumericType zy() const noexcept {
175  return xx_xy_xz_yy_yz_zz_[4];
176  }
177 
178  /// \brief Returns this three-dimensional symmetric dyadic tensor's zz Cartesian component.
179  [[nodiscard]] constexpr NumericType zz() const noexcept {
180  return xx_xy_xz_yy_yz_zz_[5];
181  }
182 
183  /// \brief Returns this three-dimensional symmetric dyadic tensor's xx, xy, xz, yy, yz, and zz
184  /// Cartesian components as a mutable array.
185  [[nodiscard]] constexpr std::array<NumericType, 6>& Mutable_xx_xy_xz_yy_yz_zz() noexcept {
186  return xx_xy_xz_yy_yz_zz_;
187  }
188 
189  /// \brief Returns this three-dimensional symmetric dyadic tensor's xx Cartesian component as a
190  /// mutable value.
191  [[nodiscard]] constexpr NumericType& Mutable_xx() noexcept {
192  return xx_xy_xz_yy_yz_zz_[0];
193  }
194 
195  /// \brief Returns this three-dimensional symmetric dyadic tensor's xy = yx Cartesian component as
196  /// a mutable value.
197  [[nodiscard]] constexpr NumericType& Mutable_xy() noexcept {
198  return xx_xy_xz_yy_yz_zz_[1];
199  }
200 
201  /// \brief Returns this three-dimensional symmetric dyadic tensor's xz = zx Cartesian component as
202  /// a mutable value.
203  [[nodiscard]] constexpr NumericType& Mutable_xz() noexcept {
204  return xx_xy_xz_yy_yz_zz_[2];
205  }
206 
207  /// \brief Returns this three-dimensional symmetric dyadic tensor's yx = xy Cartesian component as
208  /// a mutable value.
209  [[nodiscard]] constexpr NumericType& Mutable_yx() noexcept {
210  return xx_xy_xz_yy_yz_zz_[1];
211  }
212 
213  /// \brief Returns this three-dimensional symmetric dyadic tensor's yy Cartesian component as a
214  /// mutable value.
215  [[nodiscard]] constexpr NumericType& Mutable_yy() noexcept {
216  return xx_xy_xz_yy_yz_zz_[3];
217  }
218 
219  /// \brief Returns this three-dimensional symmetric dyadic tensor's yz = zy Cartesian component as
220  /// a mutable value.
221  [[nodiscard]] constexpr NumericType& Mutable_yz() noexcept {
222  return xx_xy_xz_yy_yz_zz_[4];
223  }
224 
225  /// \brief Returns this three-dimensional symmetric dyadic tensor's zx = xz Cartesian component as
226  /// a mutable value.
227  [[nodiscard]] constexpr NumericType& Mutable_zx() noexcept {
228  return xx_xy_xz_yy_yz_zz_[2];
229  }
230 
231  /// \brief Returns this three-dimensional symmetric dyadic tensor's zy = yz Cartesian component as
232  /// a mutable value.
233  [[nodiscard]] constexpr NumericType& Mutable_zy() noexcept {
234  return xx_xy_xz_yy_yz_zz_[4];
235  }
236 
237  /// \brief Returns this three-dimensional symmetric dyadic tensor's zz Cartesian component as a
238  /// mutable value.
239  [[nodiscard]] constexpr NumericType& Mutable_zz() noexcept {
240  return xx_xy_xz_yy_yz_zz_[5];
241  }
242 
243  /// \brief Sets this three-dimensional symmetric dyadic tensor's xx, xy, xz, yy, yz, and zz
244  /// Cartesian components to the given values.
245  constexpr void Set_xx_xy_xz_yy_yz_zz(
246  const std::array<NumericType, 6>& xx_xy_xz_yy_yz_zz) noexcept {
248  }
249 
250  /// \brief Sets this three-dimensional symmetric dyadic tensor's xx, xy, xz, yy, yz, and zz
251  /// Cartesian components to the given values.
252  constexpr void Set_xx_xy_xz_yy_yz_zz(
253  const NumericType xx, const NumericType xy, const NumericType xz, const NumericType yy,
254  const NumericType yz, const NumericType zz) noexcept {
255  xx_xy_xz_yy_yz_zz_[0] = xx;
256  xx_xy_xz_yy_yz_zz_[1] = xy;
257  xx_xy_xz_yy_yz_zz_[2] = xz;
258  xx_xy_xz_yy_yz_zz_[3] = yy;
259  xx_xy_xz_yy_yz_zz_[4] = yz;
260  xx_xy_xz_yy_yz_zz_[5] = zz;
261  }
262 
263  /// \brief Sets this three-dimensional symmetric dyadic tensor's xx Cartesian component to a given
264  /// value.
265  constexpr void Set_xx(const NumericType xx) noexcept {
266  xx_xy_xz_yy_yz_zz_[0] = xx;
267  }
268 
269  /// \brief Sets this three-dimensional symmetric dyadic tensor's xy = yx Cartesian component to a
270  /// given value.
271  constexpr void Set_xy(const NumericType xy) noexcept {
272  xx_xy_xz_yy_yz_zz_[1] = xy;
273  }
274 
275  /// \brief Sets this three-dimensional symmetric dyadic tensor's xz = zx Cartesian component to a
276  /// given value.
277  constexpr void Set_xz(const NumericType xz) noexcept {
278  xx_xy_xz_yy_yz_zz_[2] = xz;
279  }
280 
281  /// \brief Sets this three-dimensional symmetric dyadic tensor's yx = xy Cartesian component to a
282  /// given value.
283  constexpr void Set_yx(const NumericType yx) noexcept {
284  xx_xy_xz_yy_yz_zz_[1] = yx;
285  }
286 
287  /// \brief Sets this three-dimensional symmetric dyadic tensor's yy Cartesian component to a given
288  /// value.
289  constexpr void Set_yy(const NumericType yy) noexcept {
290  xx_xy_xz_yy_yz_zz_[3] = yy;
291  }
292 
293  /// \brief Sets this three-dimensional symmetric dyadic tensor's yz = zy Cartesian component to a
294  /// given value.
295  constexpr void Set_yz(const NumericType yz) noexcept {
296  xx_xy_xz_yy_yz_zz_[4] = yz;
297  }
298 
299  /// \brief Sets this three-dimensional symmetric dyadic tensor's zx = xz Cartesian component to a
300  /// given value.
301  constexpr void Set_zx(const NumericType zx) noexcept {
302  xx_xy_xz_yy_yz_zz_[2] = zx;
303  }
304 
305  /// \brief Sets this three-dimensional symmetric dyadic tensor's zy = yz Cartesian component to a
306  /// given value.
307  constexpr void Set_zy(const NumericType zy) noexcept {
308  xx_xy_xz_yy_yz_zz_[4] = zy;
309  }
310 
311  /// \brief Sets this three-dimensional symmetric dyadic tensor's zz Cartesian component to a given
312  /// value.
313  constexpr void Set_zz(const NumericType zz) noexcept {
314  xx_xy_xz_yy_yz_zz_[5] = zz;
315  }
316 
317  /// \brief Returns the trace of this three-dimensional symmetric dyadic tensor.
318  [[nodiscard]] constexpr NumericType Trace() const noexcept {
319  return xx() + yy() + zz();
320  }
321 
322  /// \brief Returns the determinant of this three-dimensional symmetric dyadic tensor.
323  [[nodiscard]] constexpr NumericType Determinant() const noexcept {
324  return xx() * (yy() * zz() - yz() * zy()) + xy() * (yz() * zx() - yx() * zz())
325  + xz() * (yx() * zy() - yy() * zx());
326  }
327 
328  /// \brief Returns the transpose of this three-dimensional symmetric dyadic tensor.
329  [[nodiscard]] constexpr const SymmetricDyad<NumericType>& Transpose() const noexcept {
330  return *this;
331  }
332 
333  /// \brief Returns the cofactors of this three-dimensional symmetric dyadic tensor.
334  [[nodiscard]] constexpr SymmetricDyad<NumericType> Cofactors() const {
335  const NumericType cofactor_xx{yy() * zz() - yz() * yz()};
336  const NumericType cofactor_xy{xz() * yz() - xy() * zz()};
337  const NumericType cofactor_xz{xy() * yz() - xz() * yy()};
338  const NumericType cofactor_yy{xx() * zz() - xz() * xz()};
339  const NumericType cofactor_yz{xy() * xz() - xx() * yz()};
340  const NumericType cofactor_zz{xx() * yy() - xy() * xy()};
342  cofactor_xx, cofactor_xy, cofactor_xz, cofactor_yy, cofactor_yz, cofactor_zz};
343  }
344 
345  /// \brief Returns the adjugate of this three-dimensional symmetric dyadic tensor.
346  [[nodiscard]] constexpr SymmetricDyad<NumericType> Adjugate() const {
347  // In general, for a dyadic tensor, this is cofactors().transpose(), but since this is a
348  // symmetric dyadic tensor, the transpose is redundant.
349  return Cofactors();
350  }
351 
352  /// \brief Returns the inverse of this three-dimensional symmetric dyadic tensor if it exists, or
353  /// std::nullopt otherwise.
354  [[nodiscard]] std::optional<SymmetricDyad<NumericType>> Inverse() const;
355 
356  /// \brief Prints this three-dimensional symmetric dyadic tensor as a string.
357  [[nodiscard]] std::string Print() const {
358  return "(" + PhQ::Print(xx_xy_xz_yy_yz_zz_[0]) + ", " + PhQ::Print(xx_xy_xz_yy_yz_zz_[1]) + ", "
361  }
362 
363  /// \brief Serializes this three-dimensional symmetric dyadic tensor as a JSON message.
364  [[nodiscard]] std::string JSON() const {
365  return "{\"xx\":" + PhQ::Print(xx_xy_xz_yy_yz_zz_[0]) + ",\"xy\":"
367  + ",\"yy\":" + PhQ::Print(xx_xy_xz_yy_yz_zz_[3])
368  + ",\"yz\":" + PhQ::Print(xx_xy_xz_yy_yz_zz_[4])
369  + ",\"zz\":" + PhQ::Print(xx_xy_xz_yy_yz_zz_[5]) + "}";
370  }
371 
372  /// \brief Serializes this three-dimensional symmetric dyadic tensor as an XML message.
373  [[nodiscard]] std::string XML() const {
374  return "<xx>" + PhQ::Print(xx_xy_xz_yy_yz_zz_[0]) + "</xx><xy>"
376  + "</xz><yy>" + PhQ::Print(xx_xy_xz_yy_yz_zz_[3]) + "</yy><yz>"
378  + "</zz>";
379  }
380 
381  /// \brief Serializes this three-dimensional symmetric dyadic tensor as a YAML message.
382  [[nodiscard]] std::string YAML() const {
383  return "{xx:" + PhQ::Print(xx_xy_xz_yy_yz_zz_[0]) + ",xy:" + PhQ::Print(xx_xy_xz_yy_yz_zz_[1])
384  + ",xz:" + PhQ::Print(xx_xy_xz_yy_yz_zz_[2]) + ",yy:" + PhQ::Print(xx_xy_xz_yy_yz_zz_[3])
385  + ",yz:" + PhQ::Print(xx_xy_xz_yy_yz_zz_[4]) + ",zz:" + PhQ::Print(xx_xy_xz_yy_yz_zz_[5])
386  + "}";
387  }
388 
389  /// \brief Adds another three-dimensional symmetric dyadic tensor to this one.
390  constexpr void operator+=(const SymmetricDyad<NumericType>& other) noexcept {
391  xx_xy_xz_yy_yz_zz_[0] += other.xx_xy_xz_yy_yz_zz_[0];
392  xx_xy_xz_yy_yz_zz_[1] += other.xx_xy_xz_yy_yz_zz_[1];
393  xx_xy_xz_yy_yz_zz_[2] += other.xx_xy_xz_yy_yz_zz_[2];
394  xx_xy_xz_yy_yz_zz_[3] += other.xx_xy_xz_yy_yz_zz_[3];
395  xx_xy_xz_yy_yz_zz_[4] += other.xx_xy_xz_yy_yz_zz_[4];
396  xx_xy_xz_yy_yz_zz_[5] += other.xx_xy_xz_yy_yz_zz_[5];
397  }
398 
399  /// \brief Subtracts another three-dimensional symmetric dyadic tensor from this one.
400  constexpr void operator-=(const SymmetricDyad<NumericType>& other) noexcept {
401  xx_xy_xz_yy_yz_zz_[0] -= other.xx_xy_xz_yy_yz_zz_[0];
402  xx_xy_xz_yy_yz_zz_[1] -= other.xx_xy_xz_yy_yz_zz_[1];
403  xx_xy_xz_yy_yz_zz_[2] -= other.xx_xy_xz_yy_yz_zz_[2];
404  xx_xy_xz_yy_yz_zz_[3] -= other.xx_xy_xz_yy_yz_zz_[3];
405  xx_xy_xz_yy_yz_zz_[4] -= other.xx_xy_xz_yy_yz_zz_[4];
406  xx_xy_xz_yy_yz_zz_[5] -= other.xx_xy_xz_yy_yz_zz_[5];
407  }
408 
409  /// \brief Multiplies this three-dimensional symmetric dyadic tensor by the given number.
410  /// \tparam OtherNumericType Floating-point numeric type of the given number. Deduced
411  /// automatically.
412  template <typename OtherNumericType>
413  constexpr void operator*=(const OtherNumericType number) noexcept {
414  xx_xy_xz_yy_yz_zz_[0] *= static_cast<NumericType>(number);
415  xx_xy_xz_yy_yz_zz_[1] *= static_cast<NumericType>(number);
416  xx_xy_xz_yy_yz_zz_[2] *= static_cast<NumericType>(number);
417  xx_xy_xz_yy_yz_zz_[3] *= static_cast<NumericType>(number);
418  xx_xy_xz_yy_yz_zz_[4] *= static_cast<NumericType>(number);
419  xx_xy_xz_yy_yz_zz_[5] *= static_cast<NumericType>(number);
420  }
421 
422  /// \brief Divides this three-dimensional symmetric dyadic tensor by the given number.
423  /// \tparam OtherNumericType Floating-point numeric type of the given number. Deduced
424  /// automatically.
425  template <typename OtherNumericType>
426  constexpr void operator/=(const OtherNumericType number) noexcept {
427  xx_xy_xz_yy_yz_zz_[0] /= static_cast<NumericType>(number);
428  xx_xy_xz_yy_yz_zz_[1] /= static_cast<NumericType>(number);
429  xx_xy_xz_yy_yz_zz_[2] /= static_cast<NumericType>(number);
430  xx_xy_xz_yy_yz_zz_[3] /= static_cast<NumericType>(number);
431  xx_xy_xz_yy_yz_zz_[4] /= static_cast<NumericType>(number);
432  xx_xy_xz_yy_yz_zz_[5] /= static_cast<NumericType>(number);
433  }
434 
435 private:
436  /// \brief Cartesian components of this three-dimensional symmetric dyadic tensor.
437  std::array<NumericType, 6> xx_xy_xz_yy_yz_zz_;
438 };
439 
440 template <typename NumericType>
441 inline constexpr bool operator==(
442  const SymmetricDyad<NumericType>& left, const SymmetricDyad<NumericType>& right) noexcept {
443  return (left.xx() == right.xx() && left.xy() == right.xy() && left.xz() == right.xz()
444  && left.yy() == right.yy() && left.yz() == right.yz() && left.zz() == right.zz());
445 }
446 
447 template <typename NumericType>
448 inline constexpr bool operator!=(
449  const SymmetricDyad<NumericType>& left, const SymmetricDyad<NumericType>& right) noexcept {
450  return (left.xx() != right.xx() || left.xy() != right.xy() || left.xz() != right.xz()
451  || left.yy() != right.yy() || left.yz() != right.yz() || left.zz() != right.zz());
452 }
453 
454 template <typename NumericType>
455 inline constexpr bool operator<(
456  const SymmetricDyad<NumericType>& left, const SymmetricDyad<NumericType>& right) noexcept {
457  if (left.xx() != right.xx()) {
458  return left.xx() < right.xx();
459  }
460  if (left.xy() != right.xy()) {
461  return left.xy() < right.xy();
462  }
463  if (left.xz() != right.xz()) {
464  return left.xz() < right.xz();
465  }
466  if (left.yy() != right.yy()) {
467  return left.yy() < right.yy();
468  }
469  if (left.yz() != right.yz()) {
470  return left.yz() < right.yz();
471  }
472  return left.zz() < right.zz();
473 }
474 
475 template <typename NumericType>
476 inline constexpr bool operator>(
477  const SymmetricDyad<NumericType>& left, const SymmetricDyad<NumericType>& right) noexcept {
478  if (left.xx() != right.xx()) {
479  return left.xx() > right.xx();
480  }
481  if (left.xy() != right.xy()) {
482  return left.xy() > right.xy();
483  }
484  if (left.xz() != right.xz()) {
485  return left.xz() > right.xz();
486  }
487  if (left.yy() != right.yy()) {
488  return left.yy() > right.yy();
489  }
490  if (left.yz() != right.yz()) {
491  return left.yz() > right.yz();
492  }
493  return left.zz() > right.zz();
494 }
495 
496 template <typename NumericType>
497 inline constexpr bool operator<=(
498  const SymmetricDyad<NumericType>& left, const SymmetricDyad<NumericType>& right) noexcept {
499  return !(left > right);
500 }
501 
502 template <typename NumericType>
503 inline constexpr bool operator>=(
504  const SymmetricDyad<NumericType>& left, const SymmetricDyad<NumericType>& right) noexcept {
505  return !(left < right);
506 }
507 
508 template <typename NumericType>
510  const SymmetricDyad<NumericType>& left, const SymmetricDyad<NumericType>& right) {
512  left.xx() + right.xx(), left.xy() + right.xy(), left.xz() + right.xz(),
513  left.yy() + right.yy(), left.yz() + right.yz(), left.zz() + right.zz()};
514 }
515 
516 template <typename NumericType>
518  const SymmetricDyad<NumericType>& left, const SymmetricDyad<NumericType>& right) {
520  left.xx() - right.xx(), left.xy() - right.xy(), left.xz() - right.xz(),
521  left.yy() - right.yy(), left.yz() - right.yz(), left.zz() - right.zz()};
522 }
523 
524 template <typename NumericType, typename OtherNumericType>
526  const SymmetricDyad<NumericType>& symmetric_dyad, const OtherNumericType number) {
528  symmetric_dyad.xx() * static_cast<NumericType>(number),
529  symmetric_dyad.xy() * static_cast<NumericType>(number),
530  symmetric_dyad.xz() * static_cast<NumericType>(number),
531  symmetric_dyad.yy() * static_cast<NumericType>(number),
532  symmetric_dyad.yz() * static_cast<NumericType>(number),
533  symmetric_dyad.zz() * static_cast<NumericType>(number)};
534 }
535 
536 template <typename NumericType, typename OtherNumericType>
538  const OtherNumericType number, const SymmetricDyad<NumericType>& symmetric_dyad) {
539  return SymmetricDyad<NumericType>{symmetric_dyad * number};
540 }
541 
542 template <typename NumericType>
543 inline constexpr Vector<NumericType> operator*(const SymmetricDyad<NumericType>& symmetric_dyad,
544  const PlanarVector<NumericType>& planar_vector) {
545  return Vector<NumericType>{
546  symmetric_dyad.xx() * planar_vector.x() + symmetric_dyad.xy() * planar_vector.y(),
547  symmetric_dyad.xy() * planar_vector.x() + symmetric_dyad.yy() * planar_vector.y(),
548  symmetric_dyad.xz() * planar_vector.x() + symmetric_dyad.yz() * planar_vector.y()};
549 }
550 
551 template <typename NumericType>
553  const SymmetricDyad<NumericType>& symmetric_dyad, const Vector<NumericType>& vector) {
554  return Vector<NumericType>{
555  symmetric_dyad.xx() * vector.x() + symmetric_dyad.xy() * vector.y()
556  + symmetric_dyad.xz() * vector.z(),
557  symmetric_dyad.xy() * vector.x() + symmetric_dyad.yy() * vector.y()
558  + symmetric_dyad.yz() * vector.z(),
559  symmetric_dyad.xz() * vector.x() + symmetric_dyad.yz() * vector.y()
560  + symmetric_dyad.zz() * vector.z()};
561 }
562 
563 template <typename NumericType>
564 inline constexpr Dyad<NumericType> operator*(
565  const SymmetricDyad<NumericType>& left, const SymmetricDyad<NumericType>& right);
566 
567 template <typename NumericType>
568 inline constexpr Dyad<NumericType> operator*(
569  const SymmetricDyad<NumericType>& symmetric_dyad, const Dyad<NumericType>& dyad);
570 
571 template <typename NumericType, typename OtherNumericType>
573  const SymmetricDyad<NumericType>& symmetric_dyad, const OtherNumericType number) {
575  symmetric_dyad.xx() / static_cast<NumericType>(number),
576  symmetric_dyad.xy() / static_cast<NumericType>(number),
577  symmetric_dyad.xz() / static_cast<NumericType>(number),
578  symmetric_dyad.yy() / static_cast<NumericType>(number),
579  symmetric_dyad.yz() / static_cast<NumericType>(number),
580  symmetric_dyad.zz() / static_cast<NumericType>(number)};
581 }
582 
583 template <typename NumericType>
584 inline std::optional<SymmetricDyad<NumericType>> SymmetricDyad<NumericType>::Inverse() const {
585  const NumericType determinant_{Determinant()};
586  if (determinant_ != 0.0) {
587  return std::optional<SymmetricDyad>{Adjugate() / determinant_};
588  }
589  return std::nullopt;
590 }
591 
592 template <typename NumericType>
593 inline std::ostream& operator<<(std::ostream& stream, const SymmetricDyad<NumericType>& symmetric) {
594  stream << symmetric.Print();
595  return stream;
596 }
597 
598 } // namespace PhQ
599 
600 namespace std {
601 
602 template <typename NumericType>
603 struct hash<PhQ::SymmetricDyad<NumericType>> {
604  inline size_t operator()(const PhQ::SymmetricDyad<NumericType>& symmetric) const {
605  size_t result{17};
606  result = static_cast<size_t>(31) * result + hash<NumericType>()(symmetric.xx());
607  result = static_cast<size_t>(31) * result + hash<NumericType>()(symmetric.xy());
608  result = static_cast<size_t>(31) * result + hash<NumericType>()(symmetric.xz());
609  result = static_cast<size_t>(31) * result + hash<NumericType>()(symmetric.yy());
610  result = static_cast<size_t>(31) * result + hash<NumericType>()(symmetric.yz());
611  result = static_cast<size_t>(31) * result + hash<NumericType>()(symmetric.zz());
612  return result;
613  }
614 };
615 
616 } // namespace std
617 
618 #endif // PHQ_SYMMETRIC_DYAD_HPP
Two-dimensional Euclidean vector in the XY plane. Contains two components in Cartesian coordinates: x...
constexpr NumericType x() const noexcept
Returns this two-dimensional planar vector's x Cartesian component.
constexpr NumericType y() const noexcept
Returns this two-dimensional planar vector's y Cartesian component.
Symmetric three-dimensional Euclidean dyadic tensor. Contains six components in Cartesian coordinates...
std::optional< SymmetricDyad< NumericType > > Inverse() const
Returns the inverse of this three-dimensional symmetric dyadic tensor if it exists,...
constexpr NumericType xy() const noexcept
Returns this three-dimensional symmetric dyadic tensor's xy = yx Cartesian component.
constexpr void Set_zz(const NumericType zz) noexcept
Sets this three-dimensional symmetric dyadic tensor's zz Cartesian component to a given value.
constexpr NumericType & Mutable_yy() noexcept
Returns this three-dimensional symmetric dyadic tensor's yy Cartesian component as a mutable value.
std::array< NumericType, 6 > xx_xy_xz_yy_yz_zz_
Cartesian components of this three-dimensional symmetric dyadic tensor.
constexpr NumericType & Mutable_xz() noexcept
Returns this three-dimensional symmetric dyadic tensor's xz = zx Cartesian component as a mutable val...
constexpr void Set_yx(const NumericType yx) noexcept
Sets this three-dimensional symmetric dyadic tensor's yx = xy Cartesian component to a given value.
constexpr void Set_yz(const NumericType yz) noexcept
Sets this three-dimensional symmetric dyadic tensor's yz = zy Cartesian component to a given value.
constexpr SymmetricDyad< NumericType > & operator=(const SymmetricDyad< NumericType > &other)=default
Copy assignment operator. Assigns this three-dimensional symmetric dyadic tensor by copying another o...
constexpr NumericType xx() const noexcept
Returns this three-dimensional symmetric dyadic tensor's xx Cartesian component.
constexpr NumericType Trace() const noexcept
Returns the trace of this three-dimensional symmetric dyadic tensor.
constexpr const std::array< NumericType, 6 > & xx_xy_xz_yy_yz_zz() const noexcept
Returns this three-dimensional symmetric dyadic tensor's xx, xy, xz, yy, yz, and zz Cartesian compone...
std::string XML() const
Serializes this three-dimensional symmetric dyadic tensor as an XML message.
constexpr void operator*=(const OtherNumericType number) noexcept
Multiplies this three-dimensional symmetric dyadic tensor by the given number.
constexpr SymmetricDyad< NumericType > & operator=(const std::array< NumericType, 6 > &xx_xy_xz_yy_yz_zz)
Assignment operator. Assigns this three-dimensional symmetric dyadic tensor by copying a given array ...
constexpr NumericType zx() const noexcept
Returns this three-dimensional symmetric dyadic tensor's zx = xz Cartesian component.
constexpr SymmetricDyad< NumericType > Adjugate() const
Returns the adjugate of this three-dimensional symmetric dyadic tensor.
SymmetricDyad()=default
Default constructor. Constructs a three-dimensional symmetric dyadic tensor with uninitialized xx,...
constexpr void operator-=(const SymmetricDyad< NumericType > &other) noexcept
Subtracts another three-dimensional symmetric dyadic tensor from this one.
~SymmetricDyad() noexcept=default
Destructor. Destroys this three-dimensional symmetric dyadic tensor.
constexpr NumericType zz() const noexcept
Returns this three-dimensional symmetric dyadic tensor's zz Cartesian component.
constexpr NumericType & Mutable_zz() noexcept
Returns this three-dimensional symmetric dyadic tensor's zz Cartesian component as a mutable value.
constexpr NumericType & Mutable_zy() noexcept
Returns this three-dimensional symmetric dyadic tensor's zy = yz Cartesian component as a mutable val...
constexpr void Set_xx_xy_xz_yy_yz_zz(const std::array< NumericType, 6 > &xx_xy_xz_yy_yz_zz) noexcept
Sets this three-dimensional symmetric dyadic tensor's xx, xy, xz, yy, yz, and zz Cartesian components...
constexpr SymmetricDyad< NumericType > Cofactors() const
Returns the cofactors of this three-dimensional symmetric dyadic tensor.
constexpr std::array< NumericType, 6 > & Mutable_xx_xy_xz_yy_yz_zz() noexcept
Returns this three-dimensional symmetric dyadic tensor's xx, xy, xz, yy, yz, and zz Cartesian compone...
constexpr SymmetricDyad(const std::array< NumericType, 6 > &xx_xy_xz_yy_yz_zz)
Constructor. Constructs a three-dimensional symmetric dyadic tensor from a given array representing i...
constexpr void Set_xx_xy_xz_yy_yz_zz(const NumericType xx, const NumericType xy, const NumericType xz, const NumericType yy, const NumericType yz, const NumericType zz) noexcept
Sets this three-dimensional symmetric dyadic tensor's xx, xy, xz, yy, yz, and zz Cartesian components...
constexpr NumericType & Mutable_xy() noexcept
Returns this three-dimensional symmetric dyadic tensor's xy = yx Cartesian component as a mutable val...
constexpr void Set_zy(const NumericType zy) noexcept
Sets this three-dimensional symmetric dyadic tensor's zy = yz Cartesian component to a given value.
constexpr SymmetricDyad< NumericType > & operator=(SymmetricDyad< NumericType > &&other) noexcept=default
Move assignment operator. Assigns this three-dimensional symmetric dyadic tensor by moving another on...
constexpr NumericType yx() const noexcept
Returns this three-dimensional symmetric dyadic tensor's yx = xy Cartesian component.
constexpr void operator/=(const OtherNumericType number) noexcept
Divides this three-dimensional symmetric dyadic tensor by the given number.
constexpr NumericType Determinant() const noexcept
Returns the determinant of this three-dimensional symmetric dyadic tensor.
std::string JSON() const
Serializes this three-dimensional symmetric dyadic tensor as a JSON message.
constexpr void Set_xz(const NumericType xz) noexcept
Sets this three-dimensional symmetric dyadic tensor's xz = zx Cartesian component to a given value.
constexpr NumericType & Mutable_yz() noexcept
Returns this three-dimensional symmetric dyadic tensor's yz = zy Cartesian component as a mutable val...
constexpr NumericType yy() const noexcept
Returns this three-dimensional symmetric dyadic tensor's yy Cartesian component.
constexpr void Set_xy(const NumericType xy) noexcept
Sets this three-dimensional symmetric dyadic tensor's xy = yx Cartesian component to a given value.
constexpr void Set_xx(const NumericType xx) noexcept
Sets this three-dimensional symmetric dyadic tensor's xx Cartesian component to a given value.
std::string YAML() const
Serializes this three-dimensional symmetric dyadic tensor as a YAML message.
static constexpr SymmetricDyad< NumericType > Zero()
Statically creates a three-dimensional symmetric dyadic tensor with its xx, xy, xz,...
constexpr SymmetricDyad< NumericType > & operator=(const SymmetricDyad< OtherNumericType > &other)
Copy assignment operator. Assigns this three-dimensional symmetric dyadic tensor by copying another o...
constexpr NumericType & Mutable_zx() noexcept
Returns this three-dimensional symmetric dyadic tensor's zx = xz Cartesian component as a mutable val...
constexpr NumericType xz() const noexcept
Returns this three-dimensional symmetric dyadic tensor's xz = zx Cartesian component.
constexpr void Set_zx(const NumericType zx) noexcept
Sets this three-dimensional symmetric dyadic tensor's zx = xz Cartesian component to a given value.
constexpr NumericType yz() const noexcept
Returns this three-dimensional symmetric dyadic tensor's yz = zy Cartesian component.
constexpr void operator+=(const SymmetricDyad< NumericType > &other) noexcept
Adds another three-dimensional symmetric dyadic tensor to this one.
constexpr NumericType & Mutable_yx() noexcept
Returns this three-dimensional symmetric dyadic tensor's yx = xy Cartesian component as a mutable val...
constexpr NumericType & Mutable_xx() noexcept
Returns this three-dimensional symmetric dyadic tensor's xx Cartesian component as a mutable value.
constexpr void Set_yy(const NumericType yy) noexcept
Sets this three-dimensional symmetric dyadic tensor's yy Cartesian component to a given value.
constexpr NumericType zy() const noexcept
Returns this three-dimensional symmetric dyadic tensor's zy = yz Cartesian component.
constexpr SymmetricDyad(const NumericType xx, const NumericType xy, const NumericType xz, const NumericType yy, const NumericType yz, const NumericType zz)
Constructor. Constructs a three-dimensional symmetric dyadic tensor from the given xx,...
constexpr const SymmetricDyad< NumericType > & Transpose() const noexcept
Returns the transpose of this three-dimensional symmetric dyadic tensor.
std::string Print() const
Prints this three-dimensional symmetric dyadic tensor as a string.
Three-dimensional Euclidean vector. Contains three components in Cartesian coordinates: x,...
Definition: Vector.hpp:60
constexpr NumericType x() const noexcept
Returns this three-dimensional vector's x Cartesian component.
Definition: Vector.hpp:139
constexpr NumericType y() const noexcept
Returns this three-dimensional vector's y Cartesian component.
Definition: Vector.hpp:144
constexpr NumericType z() const noexcept
Returns this three-dimensional vector's z Cartesian component.
Definition: Vector.hpp:149
Namespace that encompasses all of the Physical Quantities library's content.
constexpr bool operator<(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr bool operator<=(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr Acceleration< NumericType > operator*(const NumericType number, const Acceleration< NumericType > &acceleration)
constexpr bool operator>(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr bool operator==(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr Dyad< NumericType > operator+(const Dyad< NumericType > &left, const Dyad< NumericType > &right)
Definition: Dyad.hpp:568
constexpr Dyad< NumericType > operator-(const Dyad< NumericType > &left, const Dyad< NumericType > &right)
Definition: Dyad.hpp:576
constexpr bool operator>=(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr Dyad< NumericType > operator/(const Dyad< NumericType > &dyad, const OtherNumericType number)
Definition: Dyad.hpp:696
constexpr bool operator!=(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
std::ostream & operator<<(std::ostream &stream, const Acceleration< NumericType > &acceleration)
std::string Print(const NumericType value)
Prints a given floating-point number as a string. Prints enough digits to represent the number exactl...
Definition: Base.hpp:170