Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines the class Rotation.
6 :
7 : #pragma once
8 :
9 : #include <array>
10 : #include <cstddef>
11 : #include <limits>
12 : #include <optional>
13 :
14 : #include "DataStructures/Tensor/Tensor.hpp"
15 :
16 : /// \cond
17 : namespace PUP {
18 : class er;
19 : } // namespace PUP
20 : /// \endcond
21 :
22 : namespace domain {
23 : namespace CoordinateMaps {
24 :
25 : /// \cond HIDDEN_SYMBOLS
26 : template <size_t Dim>
27 : class Rotation;
28 : /// \endcond
29 :
30 : /*!
31 : * \ingroup CoordinateMapsGroup
32 : * \brief Spatial rotation in two dimensions.
33 : *
34 : * Let \f$(R,\Phi)\f$ be the polar coordinates associated with
35 : * \f$(\xi,\eta)\f$.
36 : * Let \f$(r,\phi)\f$ be the polar coordinates associated with \f$(x,y)\f$.
37 : * Applies the spatial rotation \f$\phi = \Phi + \alpha\f$.
38 : *
39 : * The formula for the mapping is:
40 : *\f{eqnarray*}
41 : x &=& \xi \cos \alpha - \eta \sin \alpha \\
42 : y &=& \xi \sin \alpha + \eta \cos \alpha
43 : \f}.
44 : */
45 : template <>
46 1 : class Rotation<2> {
47 : public:
48 0 : static constexpr size_t dim = 2;
49 :
50 : /// Constructor.
51 : ///
52 : /// \param rotation_angle the angle \f$\alpha\f$ (in radians).
53 1 : explicit Rotation(double rotation_angle);
54 0 : Rotation() = default;
55 0 : ~Rotation() = default;
56 0 : Rotation(const Rotation&) = default;
57 0 : Rotation& operator=(const Rotation&) = default;
58 0 : Rotation(Rotation&&) = default; // NOLINT
59 0 : Rotation& operator=(Rotation&&) = default;
60 :
61 : template <typename T>
62 0 : std::array<T, 2> operator()(const std::array<T, 2>& source_coords) const;
63 :
64 : /// The inverse function is only callable with doubles because the inverse
65 : /// might fail if called for a point out of range, and it is unclear
66 : /// what should happen if the inverse were to succeed for some points in a
67 : /// DataVector but fail for other points.
68 1 : std::optional<std::array<double, 2>> inverse(
69 : const std::array<double, 2>& target_coords) const;
70 :
71 : template <typename T>
72 0 : tnsr::Ij<T, 2, Frame::NoFrame> jacobian(
73 : const std::array<T, 2>& source_coords) const;
74 :
75 : template <typename T>
76 0 : tnsr::Ij<T, 2, Frame::NoFrame> inv_jacobian(
77 : const std::array<T, 2>& source_coords) const;
78 :
79 : // NOLINTNEXTLINE(google-runtime-references)
80 0 : void pup(PUP::er& p);
81 :
82 0 : bool is_identity() const { return is_identity_; }
83 :
84 0 : static constexpr bool supports_hessian{true};
85 :
86 : private:
87 0 : friend bool operator==(const Rotation<2>& lhs, const Rotation<2>& rhs);
88 :
89 0 : double rotation_angle_{std::numeric_limits<double>::signaling_NaN()};
90 0 : tnsr::ij<double, 2, Frame::Grid> rotation_matrix_{
91 : std::numeric_limits<double>::signaling_NaN()};
92 0 : bool is_identity_{false};
93 : };
94 :
95 0 : bool operator!=(const Rotation<2>& lhs, const Rotation<2>& rhs);
96 :
97 : /*!
98 : * \ingroup CoordinateMapsGroup
99 : * \brief Spatial rotation in three dimensions using Euler angles
100 : *
101 : * Rotation angles should be specified in degrees.
102 : * First rotation \f$\alpha\f$ is about z axis.
103 : * Second rotation \f$\beta\f$ is about rotated y axis.
104 : * Third rotation \f$\gamma\f$ is about rotated z axis.
105 : * These rotations are of the \f$(\xi,\eta,\zeta)\f$ coordinate system with
106 : * respect
107 : * to the grid coordinates \f$(x,y,z)\f$.
108 : *
109 : * The formula for the mapping is:
110 : * \f{eqnarray*}
111 : * x &=& \xi (\cos\gamma \cos\beta \cos\alpha - \sin\gamma \sin\alpha)
112 : * + \eta (-\sin\gamma \cos\beta \cos\alpha - \cos\gamma \sin\alpha)
113 : * + \zeta \sin\beta \cos\alpha \\
114 : * y &=& \xi (\cos\gamma \cos\beta \sin\alpha + \sin\gamma \cos\alpha)
115 : * + \eta (-\sin\gamma \cos\beta \sin\alpha + \cos\gamma \cos\alpha)
116 : * + \zeta \sin\beta \sin\alpha \\
117 : * z &=& -\xi \cos\gamma \sin\beta + \eta \sin\gamma \sin\beta
118 : * + \zeta \cos\beta
119 : * \f}
120 : */
121 : template <>
122 1 : class Rotation<3> {
123 : public:
124 0 : static constexpr size_t dim = 3;
125 :
126 : /// Constructor.
127 : ///
128 : /// \param rotation_about_z the angle \f$\alpha\f$ (in radians).
129 : /// \param rotation_about_rotated_y the angle \f$\beta\f$ (in radians).
130 : /// \param rotation_about_rotated_z the angle \f$\gamma\f$ (in radians).
131 1 : Rotation(double rotation_about_z, double rotation_about_rotated_y,
132 : double rotation_about_rotated_z);
133 0 : Rotation() = default;
134 0 : ~Rotation() = default;
135 0 : Rotation(const Rotation&) = default;
136 0 : Rotation& operator=(const Rotation&) = default;
137 0 : Rotation(Rotation&&) = default; // NOLINT
138 0 : Rotation& operator=(Rotation&&) = default;
139 :
140 : template <typename T>
141 0 : std::array<T, 3> operator()(const std::array<T, 3>& source_coords) const;
142 :
143 0 : std::optional<std::array<double, 3>> inverse(
144 : const std::array<double, 3>& target_coords) const;
145 :
146 : template <typename T>
147 0 : tnsr::Ij<T, 3, Frame::NoFrame> jacobian(
148 : const std::array<T, 3>& source_coords) const;
149 :
150 : template <typename T>
151 0 : tnsr::Ij<T, 3, Frame::NoFrame> inv_jacobian(
152 : const std::array<T, 3>& source_coords) const;
153 :
154 : // NOLINTNEXTLINE(google-runtime-references)
155 0 : void pup(PUP::er& p);
156 :
157 0 : bool is_identity() const { return is_identity_; }
158 :
159 0 : static constexpr bool supports_hessian{true};
160 :
161 : private:
162 0 : friend bool operator==(const Rotation<3>& lhs, const Rotation<3>& rhs);
163 :
164 0 : double rotation_about_z_{std::numeric_limits<double>::signaling_NaN()};
165 0 : double rotation_about_rotated_y_{
166 : std::numeric_limits<double>::signaling_NaN()};
167 0 : double rotation_about_rotated_z_{
168 : std::numeric_limits<double>::signaling_NaN()};
169 0 : tnsr::ij<double, 3, Frame::Grid> rotation_matrix_{
170 : std::numeric_limits<double>::signaling_NaN()};
171 0 : bool is_identity_{false};
172 : };
173 :
174 0 : bool operator!=(const Rotation<3>& lhs, const Rotation<3>& rhs);
175 :
176 : } // namespace CoordinateMaps
177 : } // namespace domain
|