Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <cstddef>
8 : #include <optional>
9 :
10 : #include "DataStructures/Tensor/Tensor.hpp"
11 : #include "Utilities/Gsl.hpp"
12 :
13 : namespace domain::CoordinateMaps {
14 :
15 : /*!
16 : * \brief Distorts cartesian coordinates \f$x^i\f$ such that a coordinate sphere
17 : * \f$\delta_{ij}x^ix^j=C^2\f$ is mapped to an ellipsoid of constant
18 : * Kerr-Schild radius \f$r=C\f$.
19 : *
20 : * The Kerr-Schild radius \f$r\f$ is defined as the largest positive
21 : * root of
22 : *
23 : * \f{equation*}{
24 : * r^4 - r^2 (x^2 - a^2) - (\vec{a}\cdot \vec{x})^2 = 0.
25 : * \f}
26 : *
27 : * In this equation, \f$\vec{x}\f$ are the coordinates of the (distorted)
28 : * surface, and \f$\vec{a}=\vec{S}/M\f$ is the spin-parameter of the black hole.
29 : * This is equivalent to the implicit definition of \f$r\f$ in Eq. (47) of
30 : * \cite Lovelace2008tw. The black hole is assumed to be at the origin.
31 : *
32 : * \details Given a spin vector \f$\vec{a}\f$, we define the Kerr-Schild radius:
33 : *
34 : * \f{equation}{r(\vec{x}) = \sqrt{\frac{x^2 - a^2 + \sqrt{(x^2 -
35 : * a^2)^2 + 4 (\vec{x} \cdot \vec{a})^2}}{2}} \f}
36 : *
37 : * We also define the auxiliary variable:
38 : *
39 : * \f{equation}{s(\vec{x}) = \frac{x^2(x^2 + a^2)}{x^4 + (\vec{x}
40 : * \cdot \vec{a})^2} \f}
41 : *
42 : * The map is then given by:
43 : *
44 : * \f{equation}{\vec{x}(\vec{\xi}) = \vec{\xi} \sqrt{s(\vec{\xi})} \f}
45 : *
46 : * The inverse map is given by:
47 : * \f{equation}{\vec{\xi}(\vec{x}) = \vec{x} \frac{r(\vec{x})}{|\vec{x}|}
48 : * \f}
49 : *
50 : * The jacobian is:
51 : * \f{equation}{ \frac{\partial \xi^i}{\partial x^j} =
52 : * \delta_{ij} \sqrt{s(\vec{\xi})} +
53 : * \frac{\xi_j}{2 \sqrt{s(\vec{\xi})}} \frac{4\xi^2(1 -
54 : * s(\vec{\xi})) \xi_j + 2a^2\xi_i + 2 s(\vec{\xi})
55 : * (\vec{\xi} \cdot \vec{a}) a_i}{\xi^4 + (\vec{\xi} \cdot
56 : * \vec{a})^2} \f}
57 : *
58 : * The inverse jacobian is:
59 : * \f{equation}{\frac{\partial x^i}{\partial \xi^j} =
60 : * \delta_{ij}\frac{r(\vec{x})}{|\vec{x}|}
61 : * + \frac{r(\vec{x})^2 x_i + (\vec{x} \cdot \vec{a})a_i}{2r(\vec{x})^3
62 : * - r(\vec{x}) (x^2 - a^2)}\frac{x_j}{|\vec{x}|} - \frac{r(\vec{x})
63 : * x_i x_j}{x^3} \f}
64 : */
65 1 : class KerrHorizonConforming {
66 : public:
67 0 : KerrHorizonConforming() = default;
68 0 : static constexpr size_t dim = 3;
69 : /*!
70 : * \brief Constructs a Kerr horizon conforming map.
71 : *
72 : * \param mass The Kerr mass parameter $M$
73 : * \param dimensionless_spin The dimensionless spin $\vec{\chi} = \vec{a} / M
74 : * = \vec{S} / M^2$, where $M$ is the Kerr mass parameter, $\vec{S}$ is the
75 : * angular momentum or quasilocal spin, and $\vec{a}$ is the Kerr spin
76 : * parameter.
77 : *
78 : * \note The horizon depends only on the dimensionful spin parameter $\vec{a}
79 : * = M \vec{\chi}$. This constructor takes $M$ and $\vec{\chi}$ separately for
80 : * consistency with other code such as gr::Solutions::KerrSchild, and hence to
81 : * avoid bugs where the wrong spin quantity is used accidentally.
82 : */
83 1 : explicit KerrHorizonConforming(const double mass,
84 : std::array<double, 3> dimensionless_spin);
85 :
86 : template <typename T>
87 0 : std::array<T, 3> operator()(const std::array<T, 3>& source_coords) const;
88 :
89 0 : std::optional<std::array<double, 3>> inverse(
90 : const std::array<double, 3>& target_coords) const;
91 :
92 : template <typename T>
93 0 : tnsr::Ij<T, 3, Frame::NoFrame> jacobian(
94 : const std::array<T, 3>& source_coords) const;
95 :
96 : template <typename T>
97 0 : tnsr::Ij<T, 3, Frame::NoFrame> inv_jacobian(
98 : const std::array<T, 3>& source_coords) const;
99 :
100 0 : bool is_identity() const {
101 : return spin_parameter_ == std::array<double, 3>{0., 0., 0.};
102 : }
103 :
104 0 : static constexpr bool supports_hessian{false};
105 :
106 0 : friend bool operator==(const KerrHorizonConforming& lhs,
107 : const KerrHorizonConforming& rhs);
108 :
109 0 : void pup(PUP::er& p);
110 :
111 : private:
112 : template <typename T>
113 0 : void stretch_factor_square(gsl::not_null<T*> result,
114 : const std::array<T, 3>& source_coords) const;
115 :
116 0 : std::array<double, 3> spin_parameter_;
117 0 : double spin_mag_sq_;
118 : };
119 0 : bool operator!=(const KerrHorizonConforming& lhs,
120 : const KerrHorizonConforming& rhs);
121 :
122 : } // namespace domain::CoordinateMaps
|