SpECTRE
v2024.09.16
|
Time-dependent spatial rotation in two or three dimensions. More...
#include <Rotation.hpp>
Public Member Functions | |
Rotation (std::string function_of_time_name) | |
template<typename T > | |
std::array< tt::remove_cvref_wrap_t< T >, Dim > | operator() (const std::array< T, Dim > &source_coords, double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time) const |
std::optional< std::array< double, Dim > > | inverse (const std::array< double, Dim > &target_coords, double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time) const |
The inverse function is only callable with doubles because the inverse might fail if called for a point out of range, and it is unclear what should happen if the inverse were to succeed for some points in a DataVector but fail for other points. | |
template<typename T > | |
std::array< tt::remove_cvref_wrap_t< T >, Dim > | frame_velocity (const std::array< T, Dim > &source_coords, double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time) const |
template<typename T > | |
tnsr::Ij< tt::remove_cvref_wrap_t< T >, Dim, Frame::NoFrame > | jacobian (const std::array< T, Dim > &source_coords, double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time) const |
template<typename T > | |
tnsr::Ij< tt::remove_cvref_wrap_t< T >, Dim, Frame::NoFrame > | inv_jacobian (const std::array< T, Dim > &source_coords, double time, const std::unordered_map< std::string, std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > > &functions_of_time) const |
void | pup (PUP::er &p) |
const std::unordered_set< std::string > & | function_of_time_names () const |
Static Public Member Functions | |
static bool | is_identity () |
Static Public Attributes | |
static constexpr size_t | dim = Dim |
Friends | |
template<size_t LocalDim> | |
bool | operator== (const Rotation< LocalDim > &lhs, const Rotation< LocalDim > &rhs) |
Time-dependent spatial rotation in two or three dimensions.
Let the source coordinates \( \vec{\xi} \) be mapped to coordinates \( \vec{x} \) using the transformation
\[ \vec{x} = R(t)\vec{\xi}, \]
where \( R(t) \) is a rotation matrix of proper dimensionality (defined below) and \( A\vec{v} \) is the standard matrix-vector multiplicaton. For 2D rotation, \( \vec{\xi} = \left(\xi, \eta\right) \) and \( \vec{x} = \left(x, y\right) \) while for 3D rotations \( \vec{\xi} = \left(\xi, \eta, \zeta\right) \) and \( \vec{x} = \left(x, y, z\right) \).
The inverse transformation is
\[ \vec{\xi} = R^T(t) \vec{x} \]
because the inverse of a rotation matrix is its transpose.
The frame velocity \( \vec{v} = d\vec{x}/dt \) is
\[ \vec{v} = \frac{d}{dt}\big( R(t) \big) \vec{\xi} \]
where \( d(R(t))/dt \) is the time derivative of the rotation matrix.
The components of the Jacobian \( \partial x^i/\partial\xi^j \) are trivially related to the components of the rotation matrix by
\[ \partial x^i/\partial\xi^j = R_{ij}, \]
and similarly the components of the inverse Jacobian \( \partial \xi^i/\partial x^j \) are
\[ \partial \xi^i/\partial x^j = R^{-1}_{ij} = R^T_{ij} = R_{ji}. \]
The 2D rotaion matrix is defined in the usual way as
\[ R(t) = \begin{bmatrix} \cos(\theta(t)) & -\sin(\theta(t)) \\ \sin(\theta(t)) & \cos(\theta(t)) \\ \end{bmatrix}. \]
We associate the polar coordinates \( \left( \mathrm{P}, \Phi\right) \) with the unmapped coordinates \( \left(\xi, \eta\right) \) and the polar coordinates \( \left(r,\phi\right) \) with the mapped coordinates \( \left(x, y\right) \). We then have \( \phi = \Phi + \theta(t) \).
The derivative of the rotation matrix is then
\[ R(t) = \begin{bmatrix} -\omega(t) \sin(\theta(t)) & -\omega(t)\cos(\theta(t)) \\ \omega(t) \cos(\theta(t)) & -\omega(t)\sin(\theta(t)) \\ \end{bmatrix}. \]
where \( \omega(t) = d\theta(t)/dt \).
For 3D rotations, we use quaternions to represent rotations about an arbitrary axis. We define a unit quaternion as
\[ \mathbf{q} = \left(q_0, q_1, q_2, q_3\right) = \left(q_0, \vec{q}\right) = \left(\cos(\frac{\theta(t)}{2}), \hat{n}\sin(\frac{\theta(t)}{2})\right) \]
where \( \hat{n} \) is our arbitrary rotation axis and \( \theta(t) \) is the angle rotated about that axis. A rotation in 3D is then defined as
\[ \mathbf{x} = \mathbf{q}\mathbf{\xi}\mathbf{q}^* \]
where \( \mathbf{q}^* = \left(\cos(\theta(t)/2), -\hat{n}\sin(\theta(t)/2)\right) \) and we promote the vectors to quaternions as \( \mathbf{x} = \left(0, \vec{x}\right) \) and \( \mathbf{\xi} = \left(0, \vec{\xi}\right) \). This will rotate the vector \( \vec{\xi} \) about \( \hat{n} \) by an angle \( \theta(t) \), transforming it into \( \vec{x} \).
We can represent this rotation using quaternions as a rotation matrix of the form
\[ R(t) = \begin{bmatrix} q_0^2 + q_1^2 - q_2^2 - q_3^2 & 2(q_1q_2 - q_0q_3) & 2(q_1q_3 + q_0q_2) \\ 2(q_1q_2 + q_0q_3) & q_0^2 + q_2^2 - q_1^2 - q_3^2 & 2(q_2q_3 - q_0q_1) \\ 2(q_1q_3 - q_0q_2) & 2(q_2q_3 + q_0q_1) & q_0^2 + q_3^2 - q_1^2 - q_2^2 \\ \end{bmatrix}. \]
The derivative of this rotation matrix can expressed in a similar form
\[ R(t) = \begin{bmatrix} 2(q_0\dot{q_0} + q_1\dot{q_1} - q_2\dot{q_2} - q_3\dot{q_3}) & 2(\dot{q_1}q_2 + q_1\dot{q_2} - \dot{q_0}q_3 - q_0\dot{q_3}) & 2(\dot{q_1}q_3 + q_1\dot{q_3} + \dot{q_0}q_2 + q_0\dot{q_2}) \\ 2(\dot{q_1}q_2 + q_1\dot{q_2} + \dot{q_0}q_3 + q_0\dot{q_3}) & 2(q_0\dot{q_0} + q_2\dot{q_2} - q_1\dot{q_1} - q_3\dot{q_3}) & 2(\dot{q_2}q_3 + q_2\dot{q_3} - \dot{q_0}q_1 - q_0\dot{q_1}) \\ 2(\dot{q_1}q_3 + q_1\dot{q_3} - \dot{q_0}q_2 - q_0\dot{q_2}) & 2(\dot{q_2}q_3 + q_2\dot{q_3} + \dot{q_0}q_1 + q_0\dot{q_1}) & 2(q_0\dot{q_0} + q_3\dot{q_3} - q_1\dot{q_1} - q_2\dot{q_2}) \\ \end{bmatrix}. \]