StrahlkorperGr.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <array>
7 
8 #include "ApparentHorizons/TagsTypeAliases.hpp"
10 
11 /// \cond
12 class DataVector;
13 class YlmSpherepack;
14 template <typename Frame>
15 class Strahlkorper;
16 template <typename X, typename Symm, typename IndexList>
17 class Tensor;
18 /// \endcond
19 
20 /// \ingroup SurfacesGroup
21 /// Contains functions that depend both on a Strahlkorper and a metric.
22 namespace StrahlkorperGr {
23 
24 /// \ingroup SurfacesGroup
25 /// \brief Computes normalized unit normal one-form to a Strahlkorper.
26 ///
27 /// \details The input argument `normal_one_form` \f$n_i\f$ is the
28 /// unnormalized surface one-form; it depends on a Strahlkorper but
29 /// not on a metric. The input argument `one_over_one_form_magnitude`
30 /// is \f$1/\sqrt{g^{ij}n_i n_j}\f$, which can be computed using (one
31 /// over) the `magnitude` function.
32 template <typename Frame>
33 tnsr::i<DataVector, 3, Frame> unit_normal_one_form(
34  const tnsr::i<DataVector, 3, Frame>& normal_one_form,
35  const DataVector& one_over_one_form_magnitude) noexcept;
36 
37 /// \ingroup SurfacesGroup
38 /// \brief Computes 3-covariant gradient \f$D_i S_j\f$ of a
39 /// Strahlkorper's normal.
40 ///
41 /// \details See Eqs. (1--9) of \cite Baumgarte1996hh.
42 /// Here \f$S_j\f$ is the (normalized) unit one-form to the surface,
43 /// and \f$D_i\f$ is the spatial covariant derivative. Note that this
44 /// object is symmetric, even though this is not obvious from the
45 /// definition. The input arguments `r_hat`, `radius`, and
46 /// `d2x_radius` depend on the Strahlkorper but not on the metric, and
47 /// can be computed from a Strahlkorper using ComputeItems in
48 /// `StrahlkorperTags`. The input argument
49 /// `one_over_one_form_magnitude` is \f$1/\sqrt{g^{ij}n_i n_j}\f$,
50 /// where \f$n_i\f$ is `StrahlkorperTags::NormalOneForm` (i.e. the
51 /// unnormalized one-form to the Strahlkorper); it can be computed
52 /// using (one over) the `magnitude` function. The input argument
53 /// `unit_normal_one_form` is \f$S_j\f$,the normalized one-form.
54 template <typename Frame>
55 tnsr::ii<DataVector, 3, Frame> grad_unit_normal_one_form(
56  const tnsr::i<DataVector, 3, Frame>& r_hat, const DataVector& radius,
57  const tnsr::i<DataVector, 3, Frame>& unit_normal_one_form,
58  const tnsr::ii<DataVector, 3, Frame>& d2x_radius,
59  const DataVector& one_over_one_form_magnitude,
60  const tnsr::Ijj<DataVector, 3, Frame>& christoffel_2nd_kind) noexcept;
61 
62 /// \ingroup SurfacesGroup
63 /// \brief Computes inverse 2-metric \f$g^{ij}-S^i S^j\f$ of a Strahlkorper.
64 ///
65 /// \details See Eqs. (1--9) of \cite Baumgarte1996hh.
66 /// Here \f$S^i\f$ is the (normalized) unit vector to the surface,
67 /// and \f$g^{ij}\f$ is the 3-metric. This object is expressed in the
68 /// usual 3-d Cartesian basis, so it is written as a 3-dimensional tensor.
69 /// But because it is orthogonal to \f$S_i\f$, it has only 3 independent
70 /// degrees of freedom, and could be expressed as a 2-d tensor with an
71 /// appropriate choice of basis. The input argument `unit_normal_vector` is
72 /// \f$S^i = g^{ij} S_j\f$, where \f$S_j\f$ is the unit normal one form.
73 template <typename Frame>
74 tnsr::II<DataVector, 3, Frame> inverse_surface_metric(
75  const tnsr::I<DataVector, 3, Frame>& unit_normal_vector,
76  const tnsr::II<DataVector, 3, Frame>& upper_spatial_metric) noexcept;
77 
78 /// \ingroup SurfacesGroup
79 /// \brief Expansion of a `Strahlkorper`. Should be zero on apparent horizons.
80 ///
81 /// \details Implements Eq. (5) in \cite Baumgarte1996hh. The input argument
82 /// `grad_normal` is the quantity returned by
83 /// `StrahlkorperGr::grad_unit_normal_one_form`, and `inverse_surface_metric`
84 /// is the quantity returned by `StrahlkorperGr::inverse_surface_metric`.
85 template <typename Frame>
87  const tnsr::ii<DataVector, 3, Frame>& grad_normal,
88  const tnsr::II<DataVector, 3, Frame>& inverse_surface_metric,
89  const tnsr::ii<DataVector, 3, Frame>& extrinsic_curvature) noexcept;
90 
91 /*!
92  * \ingroup SurfacesGroup
93  * \brief Extrinsic curvature of a 2D `Strahlkorper` embedded in a 3D space.
94  *
95  * \details Implements Eq. (D.43) of Carroll's Spacetime and Geometry text.
96  * Specifically,
97  * \f$ K_{ij} = P^k_i P^l_j \nabla_{(k} S_{l)} \f$, where
98  * \f$ P^k_i = \delta^k_i - S^k S_i \f$,
99  * `grad_normal` is the quantity \f$ \nabla_k S_l \f$ returned by
100  * `StrahlkorperGr::grad_unit_normal_one_form`, and `unit_normal_vector` is
101  * \f$S^i = g^{ij} S_j\f$ where \f$S_j\f$ is the unit normal one form.
102  * Not to be confused with the extrinsic curvature of a 3D spatial slice
103  * embedded in 3+1 spacetime.
104  * Because StrahlkorperGr::grad_unit_normal_one_form is symmetric, this
105  * can be expanded into
106  * \f$ K_{ij} = \nabla_{i}S_{j} - 2 S^k S_{(i}\nabla_{j)}S_k
107  * + S_i S_j S^k S^l \nabla_{k} n_{l}\f$.
108  */
109 template <typename Frame>
110 tnsr::ii<DataVector, 3, Frame> extrinsic_curvature(
111  const tnsr::ii<DataVector, 3, Frame>& grad_normal,
112  const tnsr::i<DataVector, 3, Frame>& unit_normal_one_form,
113  const tnsr::I<DataVector, 3, Frame>& unit_normal_vector) noexcept;
114 
115 /// \ingroup SurfacesGroup
116 /// \brief Intrinsic Ricci scalar of a 2D `Strahlkorper`.
117 ///
118 /// \details Implements Eq. (D.51) of
119 /// Sean Carroll's Spacetime and Geometry textbook (except correcting
120 /// sign errors: both extrinsic curvature terms are off by a minus sign
121 /// in Carroll's text but correct in Carroll's errata).
122 /// \f$ \hat{R}=R - 2 R_{ij} S^i S^j + K^2-K^{ij}K_{ij}.\f$
123 /// Here \f$\hat{R}\f$ is the intrinsic Ricci scalar curvature of
124 /// the Strahlkorper, \f$R\f$ and \f$R_{ij}\f$ are the Ricci scalar and
125 /// Ricci tensor of the 3D space that contains the Strahlkorper,
126 /// \f$ K_{ij} \f$ the output of StrahlkorperGr::extrinsic_curvature,
127 /// \f$ K \f$ is the trace of \f$K_{ij}\f$,
128 /// and `unit_normal_vector` is
129 /// \f$S^i = g^{ij} S_j\f$ where \f$S_j\f$ is the unit normal one form.
130 template <typename Frame>
132  const tnsr::ii<DataVector, 3, Frame>& spatial_ricci_tensor,
133  const tnsr::I<DataVector, 3, Frame>& unit_normal_vector,
134  const tnsr::ii<DataVector, 3, Frame>& extrinsic_curvature,
135  const tnsr::II<DataVector, 3, Frame>& upper_spatial_metric) noexcept;
136 
137 /*!
138  * \ingroup SurfacesGroup
139  * \brief Area element of a 2D `Strahlkorper`.
140  *
141  * \details Implements Eq. (D.13), using Eqs. (D.4) and (D.5),
142  * of \cite Baumgarte1996hh. Specifically, computes
143  * \f$\sqrt{(\Theta^i\Theta_i)(\Phi^j\Phi_j)-(\Theta^i\Phi_i)^2}\f$,
144  * \f$\Theta^i=\left(n^i(n_j-s_j) r J^j_\theta + r J^i_\theta\right)\f$,
145  * \f$\Phi^i=\left(n^i(n_j-s_j)r J^j_\phi + r J^i_\phi\right)\f$,
146  * and \f$\Theta^i\f$ and \f$\Phi^i\f$ are lowered by the
147  * 3D spatial metric \f$g_{ij}\f$. Here \f$J^i_\alpha\f$, \f$s_j\f$,
148  * \f$r\f$, and \f$n^i=n_i\f$ correspond to the input arguments
149  * `jacobian`, `normal_one_form`, `radius`, and `r_hat`, respectively;
150  * these input arguments depend only on the Strahlkorper, not on the
151  * metric, and can be computed from a Strahlkorper using ComputeItems
152  * in `StrahlkorperTags`. Note that this does not include the factor
153  * of \f$\sin\theta\f$, i.e., this returns \f$r^2\f$ for flat space.
154  * This choice makes the area element returned here compatible with
155  * `definite_integral` defined in `YlmSpherePack.hpp`.
156  */
157 template <typename Frame>
159  const tnsr::ii<DataVector, 3, Frame>& spatial_metric,
160  const StrahlkorperTags::aliases::Jacobian<Frame>& jacobian,
161  const tnsr::i<DataVector, 3, Frame>& normal_one_form,
162  const DataVector& radius,
163  const tnsr::i<DataVector, 3, Frame>& r_hat) noexcept;
164 
165 /*!
166  * \ingroup SurfacesGroup
167  * \brief Surface integral of a scalar on a 2D `Strahlkorper`
168  *
169  * \details Computes the surface integral \f$\oint dA f\f$ for a scalar \f$f\f$
170  * on a `Strahlkorper` with area element \f$dA\f$. The area element can be
171  * computed via `StrahlkorperGr::area_element()`.
172  */
173 template <typename Frame>
175  const Scalar<DataVector>& area_element, const Scalar<DataVector>& scalar,
176  const Strahlkorper<Frame>& strahlkorper) noexcept;
177 
178 /*!
179  * \ingroup SurfacesGroup
180  * \brief Spin function of a 2D `Strahlkorper`.
181  *
182  * \details See Eqs. (2) and (10)
183  * of \cite Owen2017yaj. This function computes the
184  * "spin function," which is an ingredient for horizon surface integrals that
185  * measure quasilocal spin. This function is proportional to the imaginary part
186  * of the horizon's complex scalar curvature. For Kerr black holes, the spin
187  * function is proportional to the horizon vorticity. It is also useful for
188  * visualizing the direction of a black hole's spin.
189  * Specifically, this function computes
190  * \f$\Omega = \epsilon^{AB}\nabla_A\omega_B\f$,
191  * where capital indices index the tangent bundle of the surface and
192  * where \f$\omega_\mu=(K_{\rho\nu}-K g_{\rho\nu})h_\mu^\rho s^\nu\f$ is
193  * the curl of the angular momentum density of the surface,
194  * \f$h^\rho_\mu = \delta_\mu^\rho + u_\mu u^\rho - s_\mu s^\rho\f$
195  * is the projector tangent to the 2-surface,
196  * \f$g_{\rho\nu} = \psi_{\rho\nu} + u_\rho u_\nu\f$ is the spatial
197  * metric of the spatial slice, \f$u^\rho\f$ is the unit normal to the
198  * spatial slice, and \f$s^\nu\f$ is the unit normal vector to the surface.
199  * Because the tangent basis vectors \f$e_A^\mu\f$ are
200  * orthogonal to both \f$u^\mu\f$ and \f$s^\mu\f$, it is straightforward
201  * to show that \f$\Omega = \epsilon^{AB} \nabla_A K_{B\mu}s^\mu\f$.
202  * This function uses the tangent vectors of the `Strahlkorper` to
203  * compute \f$K_{B\mu}s^\mu\f$ and then numerically computes the
204  * components of its gradient. The argument `area_element`
205  * can be computed via `StrahlkorperGr::area_element`.
206  * The argument `unit_normal_vector` can be found by raising the
207  * index of the one-form returned by `StrahlkorperGr::unit_normal_oneform`.
208  * The argument `tangents` is a Tangents that can be obtained from the
209  * StrahlkorperDataBox using the `StrahlkorperTags::Tangents` tag.
210  */
211 template <typename Frame>
213  const StrahlkorperTags::aliases::Jacobian<Frame>& tangents,
214  const YlmSpherepack& ylm,
215  const tnsr::I<DataVector, 3, Frame>& unit_normal_vector,
216  const Scalar<DataVector>& area_element,
217  const tnsr::ii<DataVector, 3, Frame>& extrinsic_curvature) noexcept;
218 
219 /*!
220  * \ingroup SurfacesGroup
221  * \brief Spin magnitude measured on a 2D `Strahlkorper`.
222  *
223  * \details Measures the quasilocal spin magnitude of a Strahlkorper, by
224  * inserting \f$\alpha=1\f$ into Eq. (10) of \cite Owen2009sb
225  * and dividing by \f$8\pi\f$ to yield the spin magnitude. The
226  * spin magnitude is a Euclidean norm of surface integrals over the horizon
227  * \f$S = \frac{1}{8\pi}\oint z \Omega dA\f$,
228  * where \f$\Omega\f$ is obtained via `StrahlkorperGr::spin_function()`,
229  * \f$dA\f$ is the area element, and \f$z\f$ (the "spin potential") is a
230  * solution of a generalized eigenproblem given by Eq. (9) of
231  * \cite Owen2009sb. Specifically,
232  * \f$\nabla^4 z + \nabla \cdot (R\nabla z) = \lambda \nabla^2 z\f$, where
233  * \f$R\f$ is obtained via `StrahlkorperGr::ricci_scalar()`. The spin
234  * magnitude is the Euclidean norm of the three values of \f$S\f$ obtained from
235  * the eigenvectors \f$z\f$ with the 3 smallest-magnitude
236  * eigenvalues \f$\lambda\f$. Note that this formulation of the eigenproblem
237  * uses the "Owen" normalization, Eq. (A9) and surrounding discussion in
238  * \cite Lovelace2008tw.
239  * The eigenvectors are normalized with the "Kerr normalization",
240  * Eq. (A22) of \cite Lovelace2008tw.
241  * The argument `spatial_metric` is the metric of the 3D spatial slice
242  * evaluated on the `Strahlkorper`.
243  * The argument `tangents` can be obtained from the StrahlkorperDataBox
244  * using the `StrahlkorperTags::Tangents` tag, and the argument
245  * `unit_normal_vector` can
246  * be found by raising the index of the one-form returned by
247  * `StrahlkorperGr::unit_normal_one_form`.
248  * The argument `ylm` is the `YlmSpherepack` of the `Strahlkorper`.
249  * The argument `area_element`
250  * can be computed via `StrahlkorperGr::area_element`.
251  */
252 template <typename Frame>
256  const tnsr::ii<DataVector, 3, Frame>& spatial_metric,
257  const StrahlkorperTags::aliases::Jacobian<Frame>& tangents,
258  const YlmSpherepack& ylm, const Scalar<DataVector>& area_element) noexcept;
259 
260 /*!
261  * \ingroup SurfacesGroup
262  * \brief Spin vector of a 2D `Strahlkorper`.
263  *
264  * \details Computes the spin vector of a `Strahlkorper` in a `Frame`, such as
265  * `Frame::Inertial`. The result is a `std::array<double, 3>` containing the
266  * Cartesian components of the spin vector, whose magnitude is
267  * `spin_magnitude`. This function will return the dimensionless spin
268  * components if `spin_magnitude` is the dimensionless spin magnitude, and
269  * it will return the dimensionful spin components if `spin_magnitude` is
270  * the dimensionful spin magnitude. The spin vector is given by
271  * a surface integral over the horizon \f$\mathcal{H}\f$ [Eq. (25) of
272  * \cite Owen2017yaj]:
273  * \f$S^i = \frac{S}{N} \oint_\mathcal{H} dA \Omega (x^i - x^i_0 - x^i_R) \f$,
274  * where \f$S\f$ is the spin magnitude,
275  * \f$N\f$ is a normalization factor enforcing \f$\delta_{ij}S^iS^j = S\f$,
276  * \f$dA\f$ is the area element (via `StrahlkorperGr::area_element`),
277  * \f$\Omega\f$ is the "spin function" (via `StrahlkorperGr::spin_function`),
278  * \f$x^i\f$ are the `Frame` coordinates of points on the `Strahlkorper`,
279  * \f$x^i_0\f$ are the `Frame` coordinates of the center of the Strahlkorper,
280  * \f$x^i_R = \frac{1}{8\pi}\oint_\mathcal{H} dA (x^i - x^i_0) R \f$,
281  * and \f$R\f$ is the intrinsic Ricci scalar of the `Strahlkorper`
282  * (via `StrahlkorperGr::ricci_scalar`).
283  * Note that measuring positions on the horizon relative to
284  * \f$x^i_0 + x^i_R\f$ instead of \f$x^i_0\f$ ensures that the mass dipole
285  * moment vanishes. Also note that \f$x^i - x^i_0\f$ is
286  * is the product of `StrahlkorperTags::Rhat` and `StrahlkorperTags::Radius`.
287  */
288 template <typename Frame>
289 std::array<double, 3> spin_vector(double spin_magnitude,
290  const Scalar<DataVector>& area_element,
291  const Scalar<DataVector>& radius,
292  const tnsr::i<DataVector, 3, Frame>& r_hat,
293  const Scalar<DataVector>& ricci_scalar,
294  const Scalar<DataVector>& spin_function,
295  const YlmSpherepack& ylm) noexcept;
296 
297 /*!
298  * \ingroup SurfacesGroup
299  * \brief Irreducible mass of a 2D `Strahlkorper`.
300  *
301  * \details See Eqs. (15.38) \cite Hartle2003gravity. This function computes the
302  * irreducible mass from the area of a horizon. Specifically, computes
303  * \f$M_\mathrm{irr}=\sqrt{\frac{A}{16\pi}}\f$.
304  */
305 double irreducible_mass(double area) noexcept;
306 } // namespace StrahlkorperGr
Scalar< DataVector > area_element(const tnsr::ii< DataVector, 3, Frame > &spatial_metric, const StrahlkorperTags::aliases::Jacobian< Frame > &jacobian, const tnsr::i< DataVector, 3, Frame > &normal_one_form, const DataVector &radius, const tnsr::i< DataVector, 3, Frame > &r_hat) noexcept
Area element of a 2D Strahlkorper.
tnsr::i< DataVector, 3, Frame > unit_normal_one_form(const tnsr::i< DataVector, 3, Frame > &normal_one_form, const DataVector &one_over_one_form_magnitude) noexcept
Computes normalized unit normal one-form to a Strahlkorper.
Scalar< DataVector > expansion(const tnsr::ii< DataVector, 3, Frame > &grad_normal, const tnsr::II< DataVector, 3, Frame > &inverse_surface_metric, const tnsr::ii< DataVector, 3, Frame > &extrinsic_curvature) noexcept
Expansion of a Strahlkorper. Should be zero on apparent horizons.
C++ interface to SPHEREPACK.
Definition: YlmSpherepack.hpp:21
tnsr::II< DataVector, 3, Frame > inverse_surface_metric(const tnsr::I< DataVector, 3, Frame > &unit_normal_vector, const tnsr::II< DataVector, 3, Frame > &upper_spatial_metric) noexcept
Computes inverse 2-metric of a Strahlkorper.
tnsr::ii< DataType, SpatialDim, Frame > spatial_metric(const tnsr::aa< DataType, SpatialDim, Frame > &spacetime_metric) noexcept
Compute spatial metric from spacetime metric.
Definition: ComputeSpacetimeQuantities.cpp:43
double surface_integral_of_scalar(const Scalar< DataVector > &area_element, const Scalar< DataVector > &scalar, const Strahlkorper< Frame > &strahlkorper) noexcept
Surface integral of a scalar on a 2D Strahlkorper
tnsr::ii< DataVector, 3, Frame > extrinsic_curvature(const tnsr::ii< DataVector, 3, Frame > &grad_normal, const tnsr::i< DataVector, 3, Frame > &unit_normal_one_form, const tnsr::I< DataVector, 3, Frame > &unit_normal_vector) noexcept
Extrinsic curvature of a 2D Strahlkorper embedded in a 3D space.
Defines a list of useful type aliases for tensors.
A star-shaped surface expanded in spherical harmonics.
Definition: Strahlkorper.hpp:21
std::array< double, 3 > spin_vector(double spin_magnitude, const Scalar< DataVector > &area_element, const Scalar< DataVector > &radius, const tnsr::i< DataVector, 3, Frame > &r_hat, const Scalar< DataVector > &ricci_scalar, const Scalar< DataVector > &spin_function, const YlmSpherepack &ylm) noexcept
Spin vector of a 2D Strahlkorper.
Stores a collection of function values.
Definition: DataVector.hpp:46
Scalar< DataVector > ricci_scalar(const tnsr::ii< DataVector, 3, Frame > &spatial_ricci_tensor, const tnsr::I< DataVector, 3, Frame > &unit_normal_vector, const tnsr::ii< DataVector, 3, Frame > &extrinsic_curvature, const tnsr::II< DataVector, 3, Frame > &upper_spatial_metric) noexcept
Intrinsic Ricci scalar of a 2D Strahlkorper.
tnsr::ii< DataVector, 3, Frame > grad_unit_normal_one_form(const tnsr::i< DataVector, 3, Frame > &r_hat, const DataVector &radius, const tnsr::i< DataVector, 3, Frame > &unit_normal_one_form, const tnsr::ii< DataVector, 3, Frame > &d2x_radius, const DataVector &one_over_one_form_magnitude, const tnsr::Ijj< DataVector, 3, Frame > &christoffel_2nd_kind) noexcept
Computes 3-covariant gradient of a Strahlkorper&#39;s normal.
Scalar< DataVector > spin_function(const StrahlkorperTags::aliases::Jacobian< Frame > &tangents, const YlmSpherepack &ylm, const tnsr::I< DataVector, 3, Frame > &unit_normal_vector, const Scalar< DataVector > &area_element, const tnsr::ii< DataVector, 3, Frame > &extrinsic_curvature) noexcept
Spin function of a 2D Strahlkorper.
double dimensionful_spin_magnitude(const Scalar< DataVector > &ricci_scalar, const Scalar< DataVector > &spin_function, const tnsr::ii< DataVector, 3, Frame > &spatial_metric, const StrahlkorperTags::aliases::Jacobian< Frame > &tangents, const YlmSpherepack &ylm, const Scalar< DataVector > &area_element) noexcept
Spin magnitude measured on a 2D Strahlkorper.
Tensor< T, Symmetry<>, index_list<> > Scalar
Scalar type.
Definition: TypeAliases.hpp:21
Contains functions that depend both on a Strahlkorper and a metric.
Definition: StrahlkorperGr.hpp:22
double irreducible_mass(double area) noexcept
Irreducible mass of a 2D Strahlkorper.