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