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 <deque>
8 : #include <string>
9 : #include <utility>
10 :
11 : #include "DataStructures/DataBox/Tag.hpp"
12 : #include "DataStructures/DataBox/TagName.hpp"
13 : #include "DataStructures/DataVector.hpp"
14 : #include "DataStructures/Tensor/EagerMath/Magnitude.hpp"
15 : #include "DataStructures/Tensor/EagerMath/RaiseOrLowerIndex.hpp"
16 : #include "DataStructures/Tensor/Tensor.hpp"
17 : #include "NumericalAlgorithms/SphericalHarmonics/Strahlkorper.hpp"
18 : #include "NumericalAlgorithms/SphericalHarmonics/TagsDeclarations.hpp"
19 : #include "NumericalAlgorithms/SphericalHarmonics/TagsTypeAliases.hpp"
20 : #include "PointwiseFunctions/GeneralRelativity/Surfaces/AreaElement.hpp"
21 : #include "PointwiseFunctions/GeneralRelativity/Surfaces/ExtrinsicCurvature.hpp"
22 : #include "PointwiseFunctions/GeneralRelativity/Surfaces/GradUnitNormalOneForm.hpp"
23 : #include "PointwiseFunctions/GeneralRelativity/Surfaces/Mass.hpp"
24 : #include "PointwiseFunctions/GeneralRelativity/Surfaces/RicciScalar.hpp"
25 : #include "PointwiseFunctions/GeneralRelativity/Surfaces/Spin.hpp"
26 : #include "PointwiseFunctions/GeneralRelativity/Surfaces/SurfaceIntegralOfScalar.hpp"
27 : #include "PointwiseFunctions/GeneralRelativity/Surfaces/SurfaceIntegralOfVector.hpp"
28 : #include "PointwiseFunctions/GeneralRelativity/Surfaces/UnitNormalOneForm.hpp"
29 : #include "PointwiseFunctions/GeneralRelativity/TagsDeclarations.hpp"
30 : #include "Utilities/ForceInline.hpp"
31 : #include "Utilities/Gsl.hpp"
32 : #include "Utilities/TMPL.hpp"
33 :
34 : /// \ingroup SurfacesGroup
35 : /// Holds tags and ComputeItems associated with a `ylm::Strahlkorper`.
36 : namespace ylm::Tags {
37 : /// The OneOverOneFormMagnitude is the reciprocal of the magnitude of the
38 : /// one-form perpendicular to the horizon
39 1 : struct OneOverOneFormMagnitude : db::SimpleTag {
40 0 : using type = DataVector;
41 : };
42 :
43 : /// Computes the reciprocal of the magnitude of the one form perpendicular to
44 : /// the horizon
45 : template <typename DataType, size_t Dim, typename Frame>
46 1 : struct OneOverOneFormMagnitudeCompute : db::ComputeTag,
47 : OneOverOneFormMagnitude {
48 0 : using base = OneOverOneFormMagnitude;
49 0 : using return_type = DataVector;
50 0 : static void function(
51 : const gsl::not_null<DataVector*> one_over_magnitude,
52 : const tnsr::II<DataType, Dim, Frame>& inverse_spatial_metric,
53 : const tnsr::i<DataType, Dim, Frame>& normal_one_form) {
54 : *one_over_magnitude =
55 : 1.0 / get(magnitude(normal_one_form, inverse_spatial_metric));
56 : }
57 0 : using argument_tags =
58 : tmpl::list<gr::Tags::InverseSpatialMetric<DataType, Dim, Frame>,
59 : NormalOneForm<Frame>>;
60 : };
61 :
62 : /// The unit normal one-form \f$s_j\f$ to the horizon.
63 : template <typename Frame>
64 1 : struct UnitNormalOneForm : db::SimpleTag {
65 0 : using type = tnsr::i<DataVector, 3, Frame>;
66 : };
67 : /// Computes the unit one-form perpendicular to the horizon
68 : template <typename Frame>
69 1 : struct UnitNormalOneFormCompute : UnitNormalOneForm<Frame>, db::ComputeTag {
70 0 : using base = UnitNormalOneForm<Frame>;
71 0 : static constexpr auto function = static_cast<void (*)(
72 : const gsl::not_null<tnsr::i<DataVector, 3, Frame>*>,
73 : const tnsr::i<DataVector, 3, Frame>&, const DataVector&)>(
74 : &::gr::surfaces::unit_normal_one_form<Frame>);
75 0 : using argument_tags =
76 : tmpl::list<ylm::Tags::NormalOneForm<Frame>, OneOverOneFormMagnitude>;
77 0 : using return_type = tnsr::i<DataVector, 3, Frame>;
78 : };
79 :
80 : /// UnitNormalVector is defined as \f$S^i = \gamma^{ij} S_j\f$,
81 : /// where \f$S_j\f$ is the unit normal one form
82 : /// and \f$\gamma^{ij}\f$ is the inverse spatial metric.
83 : template <typename Frame>
84 1 : struct UnitNormalVector : db::SimpleTag {
85 0 : using type = tnsr::I<DataVector, 3, Frame>;
86 : };
87 : /// Computes the UnitNormalVector perpendicular to the horizon.
88 : template <typename Frame>
89 1 : struct UnitNormalVectorCompute : UnitNormalVector<Frame>, db::ComputeTag {
90 0 : using base = UnitNormalVector<Frame>;
91 0 : static void function(
92 : gsl::not_null<tnsr::I<DataVector, 3, Frame>*> result,
93 : const tnsr::II<DataVector, 3, Frame>& inverse_spatial_metric,
94 : const tnsr::i<DataVector, 3, Frame>& unit_normal_one_form) {
95 : raise_or_lower_index(result, unit_normal_one_form, inverse_spatial_metric);
96 : }
97 0 : using argument_tags =
98 : tmpl::list<gr::Tags::InverseSpatialMetric<DataVector, 3, Frame>,
99 : UnitNormalOneForm<Frame>>;
100 0 : using return_type = tnsr::I<DataVector, 3, Frame>;
101 : };
102 :
103 : /// The 3-covariant gradient \f$D_i S_j\f$ of a Strahlkorper's normal
104 : template <typename Frame>
105 1 : struct GradUnitNormalOneForm : db::SimpleTag {
106 0 : using type = tnsr::ii<DataVector, 3, Frame>;
107 : };
108 : /// Computes 3-covariant gradient \f$D_i S_j\f$ of a Strahlkorper's normal
109 : template <typename Frame>
110 1 : struct GradUnitNormalOneFormCompute : GradUnitNormalOneForm<Frame>,
111 : db::ComputeTag {
112 0 : using base = GradUnitNormalOneForm<Frame>;
113 0 : static constexpr auto function = static_cast<void (*)(
114 : const gsl::not_null<tnsr::ii<DataVector, 3, Frame>*>,
115 : const tnsr::i<DataVector, 3, Frame>&, const Scalar<DataVector>&,
116 : const tnsr::i<DataVector, 3, Frame>&,
117 : const tnsr::ii<DataVector, 3, Frame>&, const DataVector&,
118 : const tnsr::Ijj<DataVector, 3, Frame>&)>(
119 : &gr::surfaces::grad_unit_normal_one_form<Frame>);
120 0 : using argument_tags =
121 : tmpl::list<Rhat<Frame>, Radius<Frame>, UnitNormalOneForm<Frame>,
122 : D2xRadius<Frame>, OneOverOneFormMagnitude,
123 : gr::Tags::SpatialChristoffelSecondKind<DataVector, 3, Frame>>;
124 0 : using return_type = tnsr::ii<DataVector, 3, Frame>;
125 : };
126 :
127 : /// Extrinsic curvature of a 2D Strahlkorper embedded in a 3D space.
128 : template <typename Frame>
129 1 : struct ExtrinsicCurvature : db::SimpleTag {
130 0 : using type = tnsr::ii<DataVector, 3, Frame>;
131 : };
132 : /// Calculates the Extrinsic curvature of a 2D Strahlkorper embedded in a 3D
133 : /// space.
134 : template <typename Frame>
135 1 : struct ExtrinsicCurvatureCompute : ExtrinsicCurvature<Frame>, db::ComputeTag {
136 0 : using base = ExtrinsicCurvature<Frame>;
137 0 : static constexpr auto function =
138 : static_cast<void (*)(const gsl::not_null<tnsr::ii<DataVector, 3, Frame>*>,
139 : const tnsr::ii<DataVector, 3, Frame>&,
140 : const tnsr::i<DataVector, 3, Frame>&,
141 : const tnsr::I<DataVector, 3, Frame>&)>(
142 : &gr::surfaces::extrinsic_curvature<Frame>);
143 0 : using argument_tags =
144 : tmpl::list<GradUnitNormalOneForm<Frame>, UnitNormalOneForm<Frame>,
145 : UnitNormalVector<Frame>>;
146 0 : using return_type = tnsr::ii<DataVector, 3, Frame>;
147 : };
148 :
149 : /// Ricci scalar is the two-dimensional intrinsic Ricci scalar curvature
150 : /// of a Strahlkorper
151 1 : struct RicciScalar : db::SimpleTag {
152 0 : using type = Scalar<DataVector>;
153 : };
154 :
155 : /// Computes the two-dimensional intrinsic Ricci scalar of a Strahlkorper
156 : template <typename Frame>
157 1 : struct RicciScalarCompute : RicciScalar, db::ComputeTag {
158 0 : using base = RicciScalar;
159 0 : static constexpr auto function = static_cast<void (*)(
160 : gsl::not_null<Scalar<DataVector>*>, const tnsr::ii<DataVector, 3, Frame>&,
161 : const tnsr::I<DataVector, 3, Frame>&,
162 : const tnsr::ii<DataVector, 3, Frame>&,
163 : const tnsr::II<DataVector, 3, Frame>&)>(
164 : &gr::surfaces::ricci_scalar<Frame>);
165 0 : using argument_tags =
166 : tmpl::list<gr::Tags::SpatialRicci<DataVector, 3, Frame>,
167 : UnitNormalVector<Frame>, ExtrinsicCurvature<Frame>,
168 : gr::Tags::InverseSpatialMetric<DataVector, 3, Frame>>;
169 0 : using return_type = Scalar<DataVector>;
170 : };
171 :
172 : /// The pointwise maximum of the Strahlkorper's intrinsic Ricci scalar
173 : /// curvature.
174 1 : struct MaxRicciScalar : db::SimpleTag {
175 0 : using type = double;
176 : };
177 :
178 : /// Computes the pointwise maximum of the Strahlkorper's intrinsic Ricci
179 : /// scalar curvature.
180 1 : struct MaxRicciScalarCompute : MaxRicciScalar, db::ComputeTag {
181 0 : using base = MaxRicciScalar;
182 0 : using return_type = double;
183 0 : static void function(const gsl::not_null<double*> max_ricci_scalar,
184 : const Scalar<DataVector>& ricci_scalar) {
185 : *max_ricci_scalar = max(get(ricci_scalar));
186 : }
187 0 : using argument_tags = tmpl::list<RicciScalar>;
188 : };
189 :
190 : /// The pointwise minimum of the Strahlkorper’s intrinsic Ricci scalar
191 : /// curvature.
192 1 : struct MinRicciScalar : db::SimpleTag {
193 0 : using type = double;
194 : };
195 :
196 : /// Computes the pointwise minimum of the Strahlkorper’s intrinsic Ricci
197 : /// scalar curvature.
198 1 : struct MinRicciScalarCompute : MinRicciScalar, db::ComputeTag {
199 0 : using base = MinRicciScalar;
200 0 : using return_type = double;
201 0 : static void function(const gsl::not_null<double*> min_ricci_scalar,
202 : const Scalar<DataVector>& ricci_scalar) {
203 : *min_ricci_scalar = min(get(ricci_scalar));
204 : }
205 0 : using argument_tags = tmpl::list<RicciScalar>;
206 : };
207 :
208 : /// @{
209 : /// Computes the Euclidean area element on a Strahlkorper.
210 : /// Useful for flat space integrals.
211 : template <typename Frame>
212 1 : struct EuclideanAreaElement : db::SimpleTag {
213 0 : using type = Scalar<DataVector>;
214 : };
215 :
216 : template <typename Frame>
217 0 : struct EuclideanAreaElementCompute : EuclideanAreaElement<Frame>,
218 : db::ComputeTag {
219 0 : using base = EuclideanAreaElement<Frame>;
220 0 : using return_type = Scalar<DataVector>;
221 0 : static constexpr auto function = static_cast<void (*)(
222 : gsl::not_null<Scalar<DataVector>*>,
223 : const ylm::Tags::aliases::Jacobian<Frame>&,
224 : const tnsr::i<DataVector, 3, Frame>&, const Scalar<DataVector>&,
225 : const tnsr::i<DataVector, 3, Frame>&)>(
226 : &::gr::surfaces::euclidean_area_element<Frame>);
227 0 : using argument_tags =
228 : tmpl::list<ylm::Tags::Jacobian<Frame>, ylm::Tags::NormalOneForm<Frame>,
229 : ylm::Tags::Radius<Frame>, ylm::Tags::Rhat<Frame>>;
230 : };
231 : /// @}
232 :
233 : /// @{
234 : /// Computes the flat-space integral of a scalar over a Strahlkorper.
235 : template <typename IntegrandTag, typename Frame>
236 1 : struct EuclideanSurfaceIntegral : db::SimpleTag {
237 0 : static std::string name() {
238 : return "EuclideanSurfaceIntegral(" + db::tag_name<IntegrandTag>() + ")";
239 : }
240 0 : using type = double;
241 : };
242 :
243 : template <typename IntegrandTag, typename Frame>
244 0 : struct EuclideanSurfaceIntegralCompute
245 : : EuclideanSurfaceIntegral<IntegrandTag, Frame>,
246 : db::ComputeTag {
247 0 : using base = EuclideanSurfaceIntegral<IntegrandTag, Frame>;
248 0 : using return_type = double;
249 0 : static void function(const gsl::not_null<double*> surface_integral,
250 : const Scalar<DataVector>& euclidean_area_element,
251 : const Scalar<DataVector>& integrand,
252 : const ylm::Strahlkorper<Frame>& strahlkorper) {
253 : *surface_integral = ::gr::surfaces::surface_integral_of_scalar<Frame>(
254 : euclidean_area_element, integrand, strahlkorper);
255 : }
256 0 : using argument_tags = tmpl::list<EuclideanAreaElement<Frame>, IntegrandTag,
257 : ylm::Tags::Strahlkorper<Frame>>;
258 : };
259 : /// @}
260 :
261 : /// @{
262 : /// Computes the Euclidean-space integral of a vector over a
263 : /// Strahlkorper, \f$\oint V^i s_i (s_j s_k \delta^{jk})^{-1/2} d^2 S\f$,
264 : /// where \f$s_i\f$ is the Strahlkorper surface unit normal and
265 : /// \f$\delta^{ij}\f$ is the Kronecker delta. Note that \f$s_i\f$ is
266 : /// not assumed to be normalized; the denominator of the integrand
267 : /// effectively normalizes it using the Euclidean metric.
268 : template <typename IntegrandTag, typename Frame>
269 1 : struct EuclideanSurfaceIntegralVector : db::SimpleTag {
270 0 : static std::string name() {
271 : return "EuclideanSurfaceIntegralVector(" + db::tag_name<IntegrandTag>() +
272 : ")";
273 : }
274 0 : using type = double;
275 : };
276 :
277 : template <typename IntegrandTag, typename Frame>
278 0 : struct EuclideanSurfaceIntegralVectorCompute
279 : : EuclideanSurfaceIntegralVector<IntegrandTag, Frame>,
280 : db::ComputeTag {
281 0 : using base = EuclideanSurfaceIntegralVector<IntegrandTag, Frame>;
282 0 : using return_type = double;
283 0 : static void function(const gsl::not_null<double*> surface_integral,
284 : const Scalar<DataVector>& euclidean_area_element,
285 : const tnsr::I<DataVector, 3, Frame>& integrand,
286 : const tnsr::i<DataVector, 3, Frame>& normal_one_form,
287 : const ylm::Strahlkorper<Frame>& strahlkorper) {
288 : *surface_integral =
289 : ::gr::surfaces::euclidean_surface_integral_of_vector<Frame>(
290 : euclidean_area_element, integrand, normal_one_form, strahlkorper);
291 : }
292 0 : using argument_tags = tmpl::list<EuclideanAreaElement<Frame>, IntegrandTag,
293 : ylm::Tags::NormalOneForm<Frame>,
294 : ylm::Tags::Strahlkorper<Frame>>;
295 : };
296 : /// @}
297 : } // namespace ylm::Tags
298 :
299 : namespace gr::surfaces {
300 : /// \ingroup SurfacesGroup
301 : /// Holds tags and ComputeItems associated with a `ylm::Strahlkorper` that
302 : /// also need a metric.
303 : namespace Tags {
304 :
305 : /// @{
306 : /// Computes the area element on a Strahlkorper. Useful for integrals.
307 : template <typename Frame>
308 1 : struct AreaElement : db::SimpleTag {
309 0 : using type = Scalar<DataVector>;
310 : };
311 :
312 : template <typename Frame>
313 0 : struct AreaElementCompute : AreaElement<Frame>, db::ComputeTag {
314 0 : using base = AreaElement<Frame>;
315 0 : using return_type = Scalar<DataVector>;
316 0 : static constexpr auto function = static_cast<void (*)(
317 : gsl::not_null<Scalar<DataVector>*>, const tnsr::ii<DataVector, 3, Frame>&,
318 : const ylm::Tags::aliases::Jacobian<Frame>&,
319 : const tnsr::i<DataVector, 3, Frame>&, const Scalar<DataVector>&,
320 : const tnsr::i<DataVector, 3, Frame>&)>(&area_element<Frame>);
321 0 : using argument_tags =
322 : tmpl::list<gr::Tags::SpatialMetric<DataVector, 3, Frame>,
323 : ylm::Tags::Jacobian<Frame>, ylm::Tags::NormalOneForm<Frame>,
324 : ylm::Tags::Radius<Frame>, ylm::Tags::Rhat<Frame>>;
325 : };
326 : /// @}
327 :
328 : /// @{
329 : /// Computes the integral of a scalar over a Strahlkorper.
330 : template <typename IntegrandTag, typename Frame>
331 1 : struct SurfaceIntegral : db::SimpleTag {
332 0 : static std::string name() {
333 : return "SurfaceIntegral(" + db::tag_name<IntegrandTag>() + ")";
334 : }
335 0 : using type = double;
336 : };
337 :
338 : template <typename IntegrandTag, typename Frame>
339 0 : struct SurfaceIntegralCompute : SurfaceIntegral<IntegrandTag, Frame>,
340 : db::ComputeTag {
341 0 : using base = SurfaceIntegral<IntegrandTag, Frame>;
342 0 : using return_type = double;
343 0 : static void function(const gsl::not_null<double*> surface_integral,
344 : const Scalar<DataVector>& area_element,
345 : const Scalar<DataVector>& integrand,
346 : const ylm::Strahlkorper<Frame>& strahlkorper) {
347 : *surface_integral = ::gr::surfaces::surface_integral_of_scalar<Frame>(
348 : area_element, integrand, strahlkorper);
349 : }
350 0 : using argument_tags = tmpl::list<AreaElement<Frame>, IntegrandTag,
351 : ylm::Tags::Strahlkorper<Frame>>;
352 : };
353 : /// @}
354 :
355 : /// Tag representing the surface area of a Strahlkorper
356 1 : struct Area : db::SimpleTag {
357 0 : using type = double;
358 : };
359 :
360 : /// Computes the surface area of a Strahlkorer, \f$A = \oint_S dA\f$ given an
361 : /// AreaElement \f$dA\f$ and a Strahlkorper \f$S\f$.
362 : template <typename Frame>
363 1 : struct AreaCompute : Area, db::ComputeTag {
364 0 : using base = Area;
365 0 : using return_type = double;
366 0 : static void function(const gsl::not_null<double*> result,
367 : const ylm::Strahlkorper<Frame>& strahlkorper,
368 : const Scalar<DataVector>& area_element) {
369 : *result = strahlkorper.ylm_spherepack().definite_integral(
370 : get(area_element).data());
371 : }
372 0 : using argument_tags =
373 : tmpl::list<ylm::Tags::Strahlkorper<Frame>, AreaElement<Frame>>;
374 : };
375 :
376 : /// The Irreducible (areal) mass of an apparent horizon
377 1 : struct IrreducibleMass : db::SimpleTag {
378 0 : using type = double;
379 : };
380 :
381 : /// Computes the Irreducible mass of an apparent horizon from its area
382 : template <typename Frame>
383 1 : struct IrreducibleMassCompute : IrreducibleMass, db::ComputeTag {
384 0 : using base = IrreducibleMass;
385 0 : using return_type = double;
386 0 : static void function(const gsl::not_null<double*> result, const double area) {
387 : *result = ::gr::surfaces::irreducible_mass(area);
388 : }
389 :
390 0 : using argument_tags = tmpl::list<Area>;
391 : };
392 :
393 : /// The spin function is proportional to the imaginary part of the
394 : /// Strahlkorper’s complex scalar curvature.
395 :
396 1 : struct SpinFunction : db::SimpleTag {
397 0 : using type = Scalar<DataVector>;
398 : };
399 :
400 : /// Calculates the spin function which is proportional to the imaginary part of
401 : /// the Strahlkorper’s complex scalar curvature.
402 : template <typename Frame>
403 1 : struct SpinFunctionCompute : SpinFunction, db::ComputeTag {
404 0 : using base = SpinFunction;
405 0 : static constexpr auto function = static_cast<void (*)(
406 : gsl::not_null<Scalar<DataVector>*>,
407 : const ylm::Tags::aliases::Jacobian<Frame>&,
408 : const ylm::Strahlkorper<Frame>&, const tnsr::I<DataVector, 3, Frame>&,
409 : const Scalar<DataVector>&, const tnsr::ii<DataVector, 3, Frame>&)>(
410 : &gr::surfaces::spin_function<Frame>);
411 0 : using argument_tags =
412 : tmpl::list<ylm::Tags::Tangents<Frame>, ylm::Tags::Strahlkorper<Frame>,
413 : ylm::Tags::UnitNormalVector<Frame>, AreaElement<Frame>,
414 : gr::Tags::ExtrinsicCurvature<DataVector, 3, Frame>>;
415 0 : using return_type = Scalar<DataVector>;
416 : };
417 :
418 : /// The approximate-Killing-Vector quasilocal spin magnitude of a Strahlkorper
419 : /// (see Sec. 2.2 of \cite Boyle2019kee and references therein).
420 1 : struct DimensionfulSpinMagnitude : db::SimpleTag {
421 0 : using type = double;
422 : };
423 :
424 : /// Computes the approximate-Killing-Vector quasilocal spin magnitude of a
425 : /// Strahlkorper
426 : template <typename Frame>
427 1 : struct DimensionfulSpinMagnitudeCompute : DimensionfulSpinMagnitude,
428 : db::ComputeTag {
429 0 : using base = DimensionfulSpinMagnitude;
430 0 : using return_type = double;
431 0 : static constexpr auto function = static_cast<void (*)(
432 : const gsl::not_null<double*>, const Scalar<DataVector>&,
433 : const Scalar<DataVector>&, const tnsr::ii<DataVector, 3, Frame>&,
434 : const ylm::Tags::aliases::Jacobian<Frame>&,
435 : const ylm::Strahlkorper<Frame>&, const Scalar<DataVector>&)>(
436 : &gr::surfaces::dimensionful_spin_magnitude<Frame>);
437 0 : using argument_tags =
438 : tmpl::list<ylm::Tags::RicciScalar, SpinFunction,
439 : gr::Tags::SpatialMetric<DataVector, 3, Frame>,
440 : ylm::Tags::Tangents<Frame>, ylm::Tags::Strahlkorper<Frame>,
441 : AreaElement<Frame>>;
442 : };
443 :
444 : /// The dimensionful spin angular momentum vector.
445 : template <typename Frame>
446 1 : struct DimensionfulSpinVector : db::SimpleTag {
447 0 : using type = std::array<double, 3>;
448 : };
449 :
450 : /// Computes the dimensionful spin angular momentum vector.
451 : template <typename MeasurementFrame, typename MetricDataFrame>
452 1 : struct DimensionfulSpinVectorCompute : DimensionfulSpinVector<MeasurementFrame>,
453 : db::ComputeTag {
454 0 : using base = DimensionfulSpinVector<MeasurementFrame>;
455 0 : using return_type = std::array<double, 3>;
456 0 : static constexpr auto function = static_cast<void (*)(
457 : const gsl::not_null<std::array<double, 3>*>, double,
458 : const Scalar<DataVector>&, const Scalar<DataVector>&,
459 : const Scalar<DataVector>&, const ylm::Strahlkorper<MetricDataFrame>&,
460 : const tnsr::I<DataVector, 3, MeasurementFrame>&)>(
461 : &gr::surfaces::spin_vector<MetricDataFrame, MeasurementFrame>);
462 0 : using argument_tags =
463 : tmpl::list<DimensionfulSpinMagnitude, AreaElement<MetricDataFrame>,
464 : ylm::Tags::RicciScalar, SpinFunction,
465 : ylm::Tags::Strahlkorper<MetricDataFrame>,
466 : ylm::Tags::CartesianCoords<MeasurementFrame>>;
467 : };
468 :
469 : /// The Christodoulou mass, which is a function of the dimensionful spin
470 : /// angular momentum and the irreducible mass of a Strahlkorper.
471 1 : struct ChristodoulouMass : db::SimpleTag {
472 0 : using type = double;
473 : };
474 :
475 : /// Computes the Christodoulou mass from the dimensionful spin angular momentum
476 : /// and the irreducible mass of a Strahlkorper.
477 : template <typename Frame>
478 1 : struct ChristodoulouMassCompute : ChristodoulouMass, db::ComputeTag {
479 0 : using base = ChristodoulouMass;
480 0 : using return_type = double;
481 0 : static void function(const gsl::not_null<double*> result,
482 : const double dimensionful_spin_magnitude,
483 : const double irreducible_mass) {
484 : *result = ::gr::surfaces::christodoulou_mass(dimensionful_spin_magnitude,
485 : irreducible_mass);
486 : }
487 :
488 0 : using argument_tags = tmpl::list<DimensionfulSpinMagnitude, IrreducibleMass>;
489 : };
490 :
491 : /// The dimensionless spin magnitude of a `Strahlkorper`.
492 : template <typename Frame>
493 1 : struct DimensionlessSpinMagnitude : db::SimpleTag {
494 0 : using type = double;
495 : };
496 :
497 : /// Computes the dimensionless spin magnitude \f$\chi = \frac{S}{M^2}\f$
498 : /// from the dimensionful spin magnitude \f$S\f$ and the christodoulou
499 : /// mass \f$M\f$ of a black hole.
500 : template <typename Frame>
501 1 : struct DimensionlessSpinMagnitudeCompute : DimensionlessSpinMagnitude<Frame>,
502 : db::ComputeTag {
503 0 : using base = DimensionlessSpinMagnitude<Frame>;
504 0 : using return_type = double;
505 0 : static constexpr auto function = static_cast<void (*)(
506 : const gsl::not_null<double*>, const double, const double)>(
507 : &gr::surfaces::dimensionless_spin_magnitude);
508 0 : using argument_tags =
509 : tmpl::list<DimensionfulSpinMagnitude, ChristodoulouMass>;
510 : };
511 :
512 : } // namespace Tags
513 : } // namespace gr::surfaces
|