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 :
8 : #include "DataStructures/Tensor/TypeAliases.hpp"
9 : #include "NumericalAlgorithms/SphericalHarmonics/TagsTypeAliases.hpp"
10 :
11 : /// \cond
12 : class DataVector;
13 : namespace ylm {
14 : template <typename Frame>
15 : class Strahlkorper;
16 : } // namespace ylm
17 : namespace gsl {
18 : template <typename>
19 : struct not_null;
20 : } // namespace gsl
21 : /// \endcond
22 :
23 : namespace gr::surfaces {
24 : /// @{
25 : /*!
26 : * \ingroup SurfacesGroup
27 : * \brief Spin function of a 2D `Strahlkorper`.
28 : *
29 : * \details See Eqs. (2) and (10)
30 : * of \cite Owen2017yaj. This function computes the
31 : * "spin function," which is an ingredient for horizon surface integrals that
32 : * measure quasilocal spin. This function is proportional to the imaginary part
33 : * of the horizon's complex scalar curvature. For Kerr black holes, the spin
34 : * function is proportional to the horizon vorticity. It is also useful for
35 : * visualizing the direction of a black hole's spin.
36 : * Specifically, this function computes
37 : * \f$\Omega = \epsilon^{AB}\nabla_A\omega_B\f$,
38 : * where capital indices index the tangent bundle of the surface and
39 : * where \f$\omega_\mu=(K_{\rho\nu}-K g_{\rho\nu})h_\mu^\rho s^\nu\f$ is
40 : * the curl of the angular momentum density of the surface,
41 : * \f$h^\rho_\mu = \delta_\mu^\rho + u_\mu u^\rho - s_\mu s^\rho\f$
42 : * is the projector tangent to the 2-surface,
43 : * \f$g_{\rho\nu} = \psi_{\rho\nu} + u_\rho u_\nu\f$ is the spatial
44 : * metric of the spatial slice, \f$u^\rho\f$ is the unit normal to the
45 : * spatial slice, and \f$s^\nu\f$ is the unit normal vector to the surface.
46 : * Because the tangent basis vectors \f$e_A^\mu\f$ are
47 : * orthogonal to both \f$u^\mu\f$ and \f$s^\mu\f$, it is straightforward
48 : * to show that \f$\Omega = \epsilon^{AB} \nabla_A K_{B\mu}s^\mu\f$.
49 : * This function uses the tangent vectors of the `Strahlkorper` to
50 : * compute \f$K_{B\mu}s^\mu\f$ and then numerically computes the
51 : * components of its gradient. The argument `area_element`
52 : * can be computed via `gr::surfaces::area_element`.
53 : * The argument `unit_normal_vector` can be found by raising the
54 : * index of the one-form returned by `gr::surfaces::unit_normal_oneform`.
55 : * The argument `tangents` is a Tangents that can be obtained from the
56 : * StrahlkorperDataBox using the `ylm::Tags::Tangents` tag.
57 : */
58 : template <typename Frame>
59 1 : void spin_function(gsl::not_null<Scalar<DataVector>*> result,
60 : const ylm::Tags::aliases::Jacobian<Frame>& tangents,
61 : const ylm::Strahlkorper<Frame>& strahlkorper,
62 : const tnsr::I<DataVector, 3, Frame>& unit_normal_vector,
63 : const Scalar<DataVector>& area_element,
64 : const tnsr::ii<DataVector, 3, Frame>& extrinsic_curvature);
65 :
66 : template <typename Frame>
67 1 : Scalar<DataVector> spin_function(
68 : const ylm::Tags::aliases::Jacobian<Frame>& tangents,
69 : const ylm::Strahlkorper<Frame>& strahlkorper,
70 : const tnsr::I<DataVector, 3, Frame>& unit_normal_vector,
71 : const Scalar<DataVector>& area_element,
72 : const tnsr::ii<DataVector, 3, Frame>& extrinsic_curvature);
73 : /// @}
74 :
75 : /// @{
76 : /*!
77 : * \ingroup SurfacesGroup
78 : * \brief Spin magnitude measured on a 2D `Strahlkorper`.
79 : *
80 : * \details Measures the quasilocal spin magnitude of a Strahlkorper, by
81 : * inserting \f$\alpha=1\f$ into Eq. (10) of \cite Owen2009sb
82 : * and dividing by \f$8\pi\f$ to yield the spin magnitude. The
83 : * spin magnitude is a Euclidean norm of surface integrals over the horizon
84 : * \f$S = \frac{1}{8\pi}\oint z \Omega dA\f$,
85 : * where \f$\Omega\f$ is obtained via `gr::surfaces::spin_function()`,
86 : * \f$dA\f$ is the area element, and \f$z\f$ (the "spin potential") is a
87 : * solution of a generalized eigenproblem given by Eq. (9) of
88 : * \cite Owen2009sb. Specifically,
89 : * \f$\nabla^4 z + \nabla \cdot (R\nabla z) = \lambda \nabla^2 z\f$, where
90 : * \f$R\f$ is obtained via `gr::surfaces::ricci_scalar()`. The spin
91 : * magnitude is the Euclidean norm of the three values of \f$S\f$ obtained from
92 : * the eigenvectors \f$z\f$ with the 3 smallest-magnitude
93 : * eigenvalues \f$\lambda\f$. Note that this formulation of the eigenproblem
94 : * uses the "Owen" normalization, Eq. (A9) and surrounding discussion in
95 : * \cite Lovelace2008tw.
96 : * The eigenvectors are normalized with the "Kerr normalization",
97 : * Eq. (A22) of \cite Lovelace2008tw.
98 : * The argument `spatial_metric` is the metric of the 3D spatial slice
99 : * evaluated on the `Strahlkorper`.
100 : * The argument `tangents` can be obtained from the StrahlkorperDataBox
101 : * using the `ylm::Tags::Tangents` tag, and the argument
102 : * `unit_normal_vector` can
103 : * be found by raising the index of the one-form returned by
104 : * `gr::surfaces::unit_normal_one_form`.
105 : * The argument `strahlkorper` is the surface on which the spin magnitude is
106 : * computed.
107 : * The argument `area_element`
108 : * can be computed via `gr::surfaces::area_element`.
109 : */
110 : template <typename Frame>
111 1 : void dimensionful_spin_magnitude(
112 : gsl::not_null<double*> result, const Scalar<DataVector>& ricci_scalar,
113 : const Scalar<DataVector>& spin_function,
114 : const tnsr::ii<DataVector, 3, Frame>& spatial_metric,
115 : const ylm::Tags::aliases::Jacobian<Frame>& tangents,
116 : const ylm::Strahlkorper<Frame>& strahlkorper,
117 : const Scalar<DataVector>& area_element);
118 :
119 : template <typename Frame>
120 1 : double dimensionful_spin_magnitude(
121 : const Scalar<DataVector>& ricci_scalar,
122 : const Scalar<DataVector>& spin_function,
123 : const tnsr::ii<DataVector, 3, Frame>& spatial_metric,
124 : const ylm::Tags::aliases::Jacobian<Frame>& tangents,
125 : const ylm::Strahlkorper<Frame>& strahlkorper,
126 : const Scalar<DataVector>& area_element);
127 : /// @}
128 :
129 : /// @{
130 : /*!
131 : * \ingroup SurfacesGroup
132 : * \brief Dimensionless spin magnitude of a `Strahlkorper`.
133 : *
134 : * \details
135 : * This function computes the dimensionless spin magnitude \f$\chi\f$
136 : * from the dimensionful spin magnitude \f$S\f$ and the christodoulou
137 : * mass \f$M\f$ of a black hole. Specifically, computes
138 : * \f$\chi = \frac{S}{M^2}\f$.
139 : */
140 :
141 1 : void dimensionless_spin_magnitude(const gsl::not_null<double*> result,
142 : const double dimensionful_spin_magnitude,
143 : const double christodoulou_mass);
144 :
145 1 : double dimensionless_spin_magnitude(const double dimensionful_spin_magnitude,
146 : const double christodoulou_mass);
147 : /// @}
148 :
149 : /*!
150 : * \ingroup SurfacesGroup
151 : * \brief Spin vector of a 2D `Strahlkorper`.
152 : *
153 : * \details Computes the spin vector of a `Strahlkorper` in a
154 : * `MeasurementFrame`, such as `Frame::Inertial`. The result is a
155 : * `std::array<double, 3>` containing the Cartesian components (in
156 : * `MeasurementFrame`) of the spin vector whose magnitude is
157 : * `spin_magnitude`. `spin_vector` will return the dimensionless spin
158 : * components if `spin_magnitude` is the dimensionless spin magnitude,
159 : * and it will return the dimensionful spin components if
160 : * `spin_magnitude` is the dimensionful spin magnitude. The spin
161 : * vector is given by
162 : * a surface integral over the horizon \f$\mathcal{H}\f$ [Eq. (25) of
163 : * \cite Owen2017yaj]:
164 : * \f$S^i = \frac{S}{N} \oint_\mathcal{H} dA \Omega (x^i - x^i_0 - x^i_R) \f$,
165 : * where \f$S\f$ is the spin magnitude,
166 : * \f$N\f$ is a normalization factor enforcing \f$\delta_{ij}S^iS^j = S\f$,
167 : * \f$dA\f$ is the area element (via `gr::surfaces::area_element`),
168 : * \f$\Omega\f$ is the "spin function" (via `gr::surfaces::spin_function`),
169 : * \f$x^i\f$ are the `MeasurementFrame` coordinates of points on
170 : * the `Strahlkorper`,
171 : * \f$x^i_0\f$ are the `MeasurementFrame` coordinates of the center
172 : * of the Strahlkorper,
173 : * \f$x^i_R = \frac{1}{8\pi}\oint_\mathcal{H} dA (x^i - x^i_0) R \f$,
174 : * and \f$R\f$ is the intrinsic Ricci scalar of the `Strahlkorper`
175 : * (via `gr::surfaces::ricci_scalar`).
176 : * Note that measuring positions on the horizon relative to
177 : * \f$x^i_0 + x^i_R\f$ instead of \f$x^i_0\f$ ensures that the mass dipole
178 : * moment vanishes.
179 : *
180 : * \param result The computed spin vector in `MeasurementFrame`.
181 : * \param spin_magnitude The spin magnitude.
182 : * \param area_element The area element on `strahlkorper`'s
183 : * collocation points.
184 : * \param ricci_scalar The intrinsic ricci scalar on `strahlkorper`'s
185 : * collocation points.
186 : * \param spin_function The spin function on `strahlkorper`'s
187 : * collocation points.
188 : * \param strahlkorper The Strahlkorper in the `MetricDataFrame` frame.
189 : * \param measurement_frame_coords The Cartesian coordinates of `strahlkorper`'s
190 : * collocation points, mapped to `MeasurementFrame`.
191 : *
192 : * Note that `spin_vector` uses two frames: the Strahlkorper and all of the
193 : * metric quantities are in `MetricDataFrame` and are used for doing integrals,
194 : * but the `measurement_frame_coordinates` are in `MeasurementFrame` and are
195 : * used for making sure the result is in the appropriate frame. The two frames
196 : * `MeasurementFrame` and `MetricDataFrame` may or may not be the same.
197 : * In principle, spin_vector could be written using only a single frame
198 : * (`MeasurementFrame`) but that would require that the metric quantities
199 : * are known on the collocation points of a Strahlkorper in `MeasurementFrame`,
200 : * which would involve more interpolation.
201 : */
202 : template <typename MetricDataFrame, typename MeasurementFrame>
203 1 : void spin_vector(
204 : const gsl::not_null<std::array<double, 3>*> result, double spin_magnitude,
205 : const Scalar<DataVector>& area_element,
206 : const Scalar<DataVector>& ricci_scalar,
207 : const Scalar<DataVector>& spin_function,
208 : const ylm::Strahlkorper<MetricDataFrame>& strahlkorper,
209 : const tnsr::I<DataVector, 3, MeasurementFrame>& measurement_frame_coords);
210 :
211 : template <typename MetricDataFrame, typename MeasurementFrame>
212 0 : std::array<double, 3> spin_vector(
213 : double spin_magnitude, const Scalar<DataVector>& area_element,
214 : const Scalar<DataVector>& ricci_scalar,
215 : const Scalar<DataVector>& spin_function,
216 : const ylm::Strahlkorper<MetricDataFrame>& strahlkorper,
217 : const tnsr::I<DataVector, 3, MeasurementFrame>& measurement_frame_coords);
218 : } // namespace gr::surfaces
|