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 <limits>
8 : #include <pup.h>
9 :
10 : #include "DataStructures/CachedTempBuffer.hpp"
11 : #include "DataStructures/Tags/TempTensor.hpp"
12 : #include "DataStructures/Tensor/IndexType.hpp"
13 : #include "DataStructures/Tensor/TypeAliases.hpp"
14 : #include "Options/Context.hpp"
15 : #include "Options/String.hpp"
16 : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp"
17 : #include "PointwiseFunctions/AnalyticSolutions/GeneralRelativity/Solutions.hpp"
18 : #include "PointwiseFunctions/GeneralRelativity/TagsDeclarations.hpp"
19 : #include "Utilities/ContainerHelpers.hpp"
20 : #include "Utilities/ForceInline.hpp"
21 : #include "Utilities/Literals.hpp"
22 : #include "Utilities/MakeArray.hpp"
23 : #include "Utilities/TMPL.hpp"
24 : #include "Utilities/TaggedTuple.hpp"
25 :
26 : /// \cond
27 : namespace Tags {
28 : template <typename Tag>
29 : struct dt;
30 : } // namespace Tags
31 : namespace gsl {
32 : template <class T>
33 : class not_null;
34 : } // namespace gsl
35 : /// \endcond
36 :
37 : namespace gr {
38 : namespace Solutions {
39 : /*!
40 : * \brief Schwarzschild black hole in Cartesian coordinates with harmonic gauge
41 : *
42 : * \details
43 : * This solution represents a Schwarzschild black hole in coordinates that are
44 : * harmonic in both space and time, as well as horizon-penetrating. Therefore,
45 : * this solution fulfills the harmonic coordinate conditions Eq. (4.42), (4.44),
46 : * and (4.45) in \cite BaumgarteShapiro :
47 : *
48 : * \f{align}
49 : * {}^{(4)}\Gamma^a &= 0
50 : * \f}
51 : *
52 : * \f{align}
53 : * (\partial_t - \beta^j \partial_j)\alpha &= -\alpha^2 K
54 : * \f}
55 : *
56 : * \f{align}
57 : * (\partial_t - \beta^j \partial_j)\beta^i &=
58 : * -\alpha^2 (\gamma^{ij} \partial_j \ln \alpha -
59 : * \gamma^{jk} \Gamma^i_{jk})
60 : * \f}
61 : *
62 : * (Note that Eq. 4.45 in \cite BaumgarteShapiro is missing a minus sign in
63 : * front of the \f$\Gamma\f$-contraction term)
64 : *
65 : * We implement Eqs. (45)--(50) in \cite Cook1997qc , which represent the
66 : * zero-spin limit of the time-harmonic and horizon-penetrating slices of Kerr
67 : * spacetime presented in the paper. We add the radial transformation
68 : * \f$r \to r + M\f$ to make the spatial coordinates harmonic as well (see
69 : * Eq. (43) in \cite Cook1997qc ), so the coordinates remain harmonic under
70 : * boosts.
71 : *
72 : * Consider a Schwarzschild black hole of mass \f$M\f$ and center \f$C^i\f$. The
73 : * spacetime will be specified using Cartesian coordinates \f$x^i\f$ that are
74 : * spatially and temporally harmonic. A radius centered on the black hole is
75 : *
76 : * \f{align}
77 : * r &= \sqrt{\delta_{ij} \left(x^i - C^i\right)\left(x^j - C^j\right)}
78 : * \f}
79 : *
80 : * For computing the spatial metric, we define the following quantities:
81 : *
82 : * \f{align}
83 : * \gamma_{rr} &= 1 + \frac{2M}{M+r} + \left(\frac{2M}{M+r}\right)^2
84 : * + \left(\frac{2M}{M+r}\right)^3,\\
85 : * \partial_r \gamma_{rr} &= -\frac{1}{2M}\left(\frac{2M}{M+r}\right)^2
86 : * -\frac{1}{M}\left(\frac{2M}{M+r}\right)^3
87 : * -\frac{3}{2M}\left(\frac{2M}{M+r}\right)^4,\\
88 : * \frac{X^i}{r} &= \frac{x^i - C^i}{r},\\
89 : * X_j &= X^i \delta_{ij}
90 : * \f}
91 : *
92 : * From these quantities, the spatial metric and its time derivative are
93 : * computed as
94 : *
95 : * \f{align}
96 : * \gamma_{ij} &=
97 : * \left(\gamma_{rr} - \left(1+\frac{M}{r}\right)^2\right)
98 : * \frac{X_i}{r} \frac{X_j}{r} +
99 : * \delta_{ij} \left(1+\frac{M}{r}\right)^2,\\
100 : * \partial_t \gamma_{ij} &= 0
101 : * \f}
102 : *
103 : * The spatial derivative is given in terms of the following quantities:
104 : *
105 : * \f{align}
106 : * f_0 &= \left(1+\frac{M}{r}\right)^2\\
107 : * \partial_r f_0 &=
108 : * 2 \left(1+\frac{M}{r}\right)\left(-\frac{M}{r^2}\right),\\
109 : * f_1 &= \frac{1}{r} \left(\gamma_{rr} - f_0\right),\\
110 : * f_2 &= \partial_r \gamma_{rr} - \partial_r f_0 - 2 f_1
111 : * \f}
112 : *
113 : * In terms of these, the spatial metric's spatial derivative is
114 : *
115 : * \f{align}
116 : * \partial_k \gamma_{ij} &=
117 : * f_2 \frac{X_i}{r} \frac{X_j}{r} \frac{X_k}{r} +
118 : * f_1 \frac{X_j}{r} \delta_{ik} + f_1 \frac{X_i}{r} \delta_{jk} +
119 : * \partial_r f_0 \frac{X_k}{r} \delta_{ij}
120 : * \f}
121 : *
122 : * The lapse and its derivatives are
123 : *
124 : * \f{align}
125 : * \alpha &= \gamma_{rr}^{-1/2},\\
126 : * \partial_t \alpha &= 0,\\
127 : * \partial_i \alpha &=
128 : * -\frac{1}{2} \gamma_{rr}^{-3/2} \partial_r \gamma_{rr} \frac{X_i}{r}
129 : * \f}
130 : *
131 : * The shift and its time derivative are
132 : *
133 : * \f{align}
134 : * \beta^i &= \left(\frac{2M}{M+r}\right)^2 \frac{X^i}{r}
135 : * \frac{1}{\gamma_{rr}},\\
136 : * \partial_t \beta^i &= 0
137 : * \f}
138 : *
139 : * The spatial derivative of the shift is computed in terms of the following
140 : * quantities:
141 : *
142 : * \f{align}
143 : * f_3 &= \frac{1}{r} \frac{1}{\gamma_{rr}} \left(\frac{2M}{M+r}\right)^2,\\
144 : * f_4 &=
145 : * -f_3 -
146 : * \frac{1}{M} \frac{1}{\gamma_{rr}}
147 : * \left(\frac{2M}{M+r}\right)^3 -
148 : * \partial_r \gamma_{rr} \left(\frac{2 M}{M+r}
149 : * \frac{1}{\gamma_{rr}}\right)^2
150 : * \f}
151 : *
152 : * In terms of these, the shift's spatial derivative is
153 : *
154 : * \f{align}
155 : * \partial_k \beta^i &= f_4 \frac{X^i}{r} \frac{X_k}{r} + \delta_k^i f_3
156 : * \f}
157 : */
158 1 : class HarmonicSchwarzschild : public AnalyticSolution<3_st>,
159 : public MarkAsAnalyticSolution {
160 : public:
161 0 : struct Mass {
162 0 : using type = double;
163 0 : static constexpr Options::String help = {"Mass of the black hole"};
164 0 : static type lower_bound() { return 0.; }
165 : };
166 0 : struct Center {
167 0 : using type = std::array<double, volume_dim>;
168 0 : static constexpr Options::String help = {
169 : "The [x,y,z] center of the black hole"};
170 : };
171 0 : using options = tmpl::list<Mass, Center>;
172 0 : static constexpr Options::String help{
173 : "Schwarzschild black hole in Cartesian coordinates with harmonic gauge"};
174 :
175 0 : HarmonicSchwarzschild(double mass,
176 : const std::array<double, volume_dim>& center,
177 : const Options::Context& context = {});
178 :
179 0 : HarmonicSchwarzschild() = default;
180 0 : HarmonicSchwarzschild(const HarmonicSchwarzschild& /*rhs*/) = default;
181 0 : HarmonicSchwarzschild& operator=(const HarmonicSchwarzschild& /*rhs*/) =
182 : default;
183 0 : HarmonicSchwarzschild(HarmonicSchwarzschild&& /*rhs*/) = default;
184 0 : HarmonicSchwarzschild& operator=(HarmonicSchwarzschild&& /*rhs*/) = default;
185 0 : ~HarmonicSchwarzschild() = default;
186 :
187 0 : explicit HarmonicSchwarzschild(CkMigrateMessage* /*msg*/);
188 :
189 : /*!
190 : * \brief Computes and returns spacetime quantities for a Schwarzschild black
191 : * hole with harmonic coordinates at a specific Cartesian position
192 : *
193 : * \param x Cartesian coordinates of the position at which to compute
194 : * spacetime quantities
195 : */
196 : template <typename DataType, typename Frame, typename... Tags>
197 1 : tuples::TaggedTuple<Tags...> variables(
198 : const tnsr::I<DataType, volume_dim, Frame>& x, double /*t*/,
199 : tmpl::list<Tags...> /*meta*/) const {
200 : static_assert(
201 : tmpl2::flat_all_v<
202 : tmpl::list_contains_v<tags<DataType, Frame>, Tags>...>,
203 : "At least one of the requested tags is not supported. The requested "
204 : "tags are listed as template parameters of the `variables` function.");
205 : IntermediateVars<DataType, Frame> cache(get_size(*x.begin()));
206 : IntermediateComputer<DataType, Frame> computer(*this, x);
207 : return {cache.get_var(computer, Tags{})...};
208 : }
209 :
210 : // NOLINTNEXTLINE(google-runtime-references)
211 0 : void pup(PUP::er& p);
212 :
213 : /*!
214 : * \brief Return the mass of the black hole
215 : */
216 1 : SPECTRE_ALWAYS_INLINE double mass() const { return mass_; }
217 : /*!
218 : * \brief Return the center of the black hole
219 : */
220 1 : SPECTRE_ALWAYS_INLINE const std::array<double, volume_dim>& center() const {
221 : return center_;
222 : }
223 :
224 : /*!
225 : * \brief Tags defined for intermediates specific to the harmonic
226 : * Schwarzschild solution
227 : */
228 1 : struct internal_tags {
229 : /*!
230 : * \brief Tag for the position of a point relative to the center of the
231 : * black hole
232 : *
233 : * \details Defined as \f$X^i = \left(x^i - C^i\right)\f$, where \f$C^i\f$
234 : * is the Cartesian coordinates of the center of the black hole
235 : * and \f$x^i\f$ is the Cartesian coordinates of the point where we're
236 : * wanting to compute spacetime quantities.
237 : */
238 : template <typename DataType, typename Frame = ::Frame::Inertial>
239 1 : using x_minus_center = ::Tags::TempI<0, 3, Frame, DataType>;
240 : /*!
241 : * \brief Tag for the radius corresponding to the position of a point
242 : * relative to the center of the black hole
243 : *
244 : * \details Defined as \f$r = \sqrt{\delta_{ij} X^i X^j}\f$, where \f$X^i\f$
245 : * is defined by `internal_tags::x_minus_center`.
246 : */
247 : template <typename DataType>
248 1 : using r = ::Tags::TempScalar<1, DataType>;
249 : /*!
250 : * \brief Tag for one over the radius corresponding to the position of a
251 : * point relative to the center of the black hole
252 : *
253 : * \details The quantity \f$r\f$ is the radius defined by
254 : * `internal_tags::r`.
255 : */
256 : template <typename DataType>
257 1 : using one_over_r = ::Tags::TempScalar<2, DataType>;
258 : /*!
259 : * \brief Tag for the intermediate \f$\frac{X^i}{r}\f$
260 : *
261 : * \details The quantity \f$X^i\f$ is defined by
262 : * `internal_tags::x_minus_center` and \f$r\f$ is the radius defined by
263 : * `internal_tags::r`.
264 : */
265 : template <typename DataType, typename Frame = ::Frame::Inertial>
266 1 : using x_over_r = ::Tags::TempI<3, 3, Frame, DataType>;
267 : /*!
268 : * \brief Tag for the intermediate \f$\frac{M}{r}\f$
269 : *
270 : * \details The quantity \f$M\f$ is the mass of the black hole and \f$r\f$
271 : * is the radius defined by `internal_tags::r`.
272 : */
273 : template <typename DataType>
274 1 : using m_over_r = ::Tags::TempScalar<4, DataType>;
275 : /*!
276 : * \brief Tag for the intermediate \f$\sqrt{f_0} = 1 + \frac{M}{r}\f$
277 : *
278 : * \details The quantity \f$M\f$ is the mass of the black hole, \f$r\f$ is
279 : * the radius defined by `internal_tags::r`, and \f$f_0\f$ is defined by
280 : * `internal_tags::f_0`.
281 : */
282 : template <typename DataType>
283 1 : using sqrt_f_0 = ::Tags::TempScalar<5, DataType>;
284 : /*!
285 : * \brief Tag for the intermediate
286 : * \f$f_0 = \left(1 + \frac{M}{r}\right)^2\f$
287 : *
288 : * \details The quantity \f$M\f$ is the mass of the black hole and \f$r\f$
289 : * is the radius defined by `internal_tags::r`.
290 : */
291 : template <typename DataType>
292 1 : using f_0 = ::Tags::TempScalar<6, DataType>;
293 : /*!
294 : * \brief Tag for the intermediate \f$\frac{2M}{M+r}\f$
295 : *
296 : * \details The quantity \f$M\f$ is the mass of the black hole and \f$r\f$
297 : * is the radius defined by `internal_tags::r`.
298 : */
299 : template <typename DataType>
300 1 : using two_m_over_m_plus_r = ::Tags::TempScalar<7, DataType>;
301 : /*!
302 : * \brief Tag for the intermediate \f$\left(\frac{2M}{M+r}\right)^2\f$
303 : *
304 : * \details The quantity \f$M\f$ is the mass of the black hole and \f$r\f$
305 : * is the radius defined by `internal_tags::r`.
306 : */
307 : template <typename DataType>
308 1 : using two_m_over_m_plus_r_squared = ::Tags::TempScalar<8, DataType>;
309 : /*!
310 : * \brief Tag for the intermediate \f$\left(\frac{2M}{M+r}\right)^3\f$
311 : *
312 : * \details The quantity \f$M\f$ is the mass of the black hole and \f$r\f$
313 : * is the radius defined by `internal_tags::r`.
314 : */
315 : template <typename DataType>
316 1 : using two_m_over_m_plus_r_cubed = ::Tags::TempScalar<9, DataType>;
317 : /*!
318 : * \brief Tag for the \f$\gamma_{rr}\f$ component of the spatial metric
319 : *
320 : * \details Defined as
321 : *
322 : * \f{align}
323 : * \gamma_{rr} &= 1 + \frac{2M}{M+r} + \left(\frac{2M}{M+r}\right)^2
324 : * + \left(\frac{2M}{M+r}\right)^3
325 : * \f}
326 : *
327 : * where \f$M\f$ is the mass of the black hole and \f$r\f$ is the radius
328 : * defined by `internal_tags::r`.
329 : */
330 : template <typename DataType>
331 1 : using spatial_metric_rr = ::Tags::TempScalar<10, DataType>;
332 : /*!
333 : * \brief Tag for the intermediate \f$\frac{1}{\gamma_{rr}}\f$
334 : *
335 : * \details The quantity \f$\gamma_{rr}\f$ is defined by
336 : * `internal_tags::spatial_metric_rr`.
337 : */
338 : template <typename DataType>
339 1 : using one_over_spatial_metric_rr = ::Tags::TempScalar<11, DataType>;
340 : /*!
341 : * \brief Tag for the intermediate \f$\gamma_{rr} - f_0\f$
342 : *
343 : * \details The quantity \f$\gamma_{rr}\f$ is defined by
344 : * `internal_tags::spatial_metric_rr` and \f$f_0\f$ is defined by
345 : * `internal_tags::f_0`.
346 : */
347 : template <typename DataType>
348 1 : using spatial_metric_rr_minus_f_0 = ::Tags::TempScalar<12, DataType>;
349 : /*!
350 : * \brief Tag for the intermediate \f$\partial_r \gamma_{rr}\f$
351 : *
352 : * \details Defined as
353 : *
354 : * \f{align}
355 : * \partial_r \gamma_{rr} &= -\frac{1}{2M}\left(\frac{2M}{M+r}\right)^2
356 : * -\frac{1}{M}\left(\frac{2M}{M+r}\right)^3
357 : * -\frac{3}{2M}\left(\frac{2M}{M+r}\right)^4
358 : * \f}
359 : *
360 : * where \f$M\f$ is the mass of the black hole and \f$r\f$ is the radius
361 : * defined by `internal_tags::r`.
362 : */
363 : template <typename DataType>
364 1 : using d_spatial_metric_rr = ::Tags::TempScalar<13, DataType>;
365 : /*!
366 : * \brief Tag for the intermediate \f$\partial_r f_0\f$
367 : *
368 : * \details Defined as
369 : *
370 : * \f{align}
371 : * \partial_r f_0 &=
372 : * 2 \left(1+\frac{M}{r}\right)\left(-\frac{M}{r^2}\right)
373 : * \f}
374 : *
375 : * where \f$M\f$ is the mass of the black hole and \f$r\f$ is the radius
376 : * defined by `internal_tags::r`.
377 : */
378 : template <typename DataType>
379 1 : using d_f_0 = ::Tags::TempScalar<14, DataType>;
380 : /*!
381 : * \brief Tag for the intermediate \f$\partial_r f_0 \frac{X_i}{r}\f$
382 : *
383 : * \details The quantity \f$r\f$ is the radius defined by
384 : * `internal_tags::r`, \f$\partial_r f_0\f$ is defined by
385 : * `internal_tags::d_f_0`, and \f$X_j = X^i \delta_{ij}\f$ where \f$X^i\f$
386 : * is defined by `internal_tags::x_minus_center`.
387 : */
388 : template <typename DataType, typename Frame = ::Frame::Inertial>
389 1 : using d_f_0_times_x_over_r = ::Tags::Tempi<15, 3, Frame, DataType>;
390 : /*!
391 : * \brief Tag for the intermediate
392 : * \f$f_1 = \frac{1}{r} \left(\gamma_{rr} - f_0\right)\f$
393 : *
394 : * \details The quantity \f$r\f$ is the radius defined by
395 : * `internal_tags::r`, \f$\gamma_{rr}\f$ is defined by
396 : * `internal_tags::spatial_metric_rr`, and \f$f_0\f$ is defined by
397 : * `internal_tags::f_0`.
398 : */
399 : template <typename DataType>
400 1 : using f_1 = ::Tags::TempScalar<16, DataType>;
401 : /*!
402 : * \brief Tag for the intermediate \f$f_1 \frac{X_i}{r}\f$
403 : *
404 : * \details The quantity \f$r\f$ is the radius defined by
405 : * `internal_tags::r`, \f$f_1\f$ is defined by `internal_tags::f_1`, and
406 : * \f$X_j = X^i \delta_{ij}\f$ where \f$X^i\f$ is defined by
407 : * `internal_tags::x_minus_center`.
408 : */
409 : template <typename DataType, typename Frame = ::Frame::Inertial>
410 1 : using f_1_times_x_over_r = ::Tags::Tempi<17, 3, Frame, DataType>;
411 : /*!
412 : * \brief Tag for the intermediate
413 : * \f$f_2 = \partial_r \gamma_{rr} - \partial_r f_0 - 2 f_1\f$
414 : *
415 : * \details The quantity \f$\partial_r \gamma_{rr}\f$ is defined by
416 : * `internal_tags::d_spatial_metric_rr`, \f$\partial_r f_0\f$ is defined by
417 : * `internal_tags::d_f_0`, and \f$f_1\f$ is defined by `internal_tags::f_1`.
418 : */
419 : template <typename DataType>
420 1 : using f_2 = ::Tags::TempScalar<18, DataType>;
421 : /*!
422 : * \brief Tag for the intermediate
423 : * \f$f_2 \frac{X_i}{r} \frac{X_j}{r} \frac{X_k}{r}\f$
424 : *
425 : * \details The quantity \f$r\f$ is the radius defined by
426 : * `internal_tags::r`, \f$f_2\f$ is defined by `internal_tags::f_2`, and
427 : * \f$X_j = X^i \delta_{ij}\f$ where \f$X^i\f$ is defined by
428 : * `internal_tags::x_minus_center`.
429 : */
430 : template <typename DataType, typename Frame = ::Frame::Inertial>
431 1 : using f_2_times_xxx_over_r_cubed = ::Tags::Tempiii<19, 3, Frame, DataType>;
432 : /*!
433 : * \brief Tag for the intermediate
434 : * \f$f_3 = \frac{1}{r}\frac{1}{\gamma_{rr}}\left(\frac{2M}{M+r}\right)^2\f$
435 : *
436 : * \details The quantity \f$M\f$ is the mass of the black hole, \f$r\f$ is
437 : * the radius defined by `internal_tags::r`, and \f$\gamma_{rr}\f$ is
438 : * defined by `internal_tags::spatial_metric_rr`.
439 : */
440 : template <typename DataType>
441 1 : using f_3 = ::Tags::TempScalar<20, DataType>;
442 : /*!
443 : * \brief Tag for the intermediate
444 : *
445 : * \f{align}
446 : * f_4 &=
447 : * -f_3 -
448 : * \frac{1}{M} \frac{1}{\gamma_{rr}}
449 : * \left(\frac{2M}{M+r}\right)^3 -
450 : * \partial_r \gamma_{rr} \left(\frac{2 M}{M+r}
451 : * \frac{1}{\gamma_{rr}}\right)^2
452 : * \f}
453 : *
454 : * \details The quantity \f$M\f$ is the mass of the black hole, \f$r\f$ is
455 : * the radius defined by `internal_tags::r`, \f$f_3\f$ is defined by
456 : * `internal_tags::f_3`, \f$\gamma_{rr}\f$ is defined by
457 : * `internal_tags::spatial_metric_rr`, and its derivative
458 : * \f$\partial_r \gamma_{rr}\f$ is defined by
459 : * `internal_tags::d_spatial_metric_rr`.
460 : */
461 : template <typename DataType>
462 1 : using f_4 = ::Tags::TempScalar<21, DataType>;
463 : /*!
464 : * \brief Tag for one over the determinant of the spatial metric
465 : */
466 : template <typename DataType>
467 1 : using one_over_det_spatial_metric = ::Tags::TempScalar<22, DataType>;
468 : /*!
469 : * \brief Tag for the intermediate
470 : * \f$-\frac{1}{2} \gamma_{rr}^{-3/2} \partial_r \gamma_{rr}\f$
471 : *
472 : * \details The lapse is defined as \f$\alpha = \gamma_{rr}^{-1/2}\f$,
473 : * \f$\gamma_{rr}\f$ is defined by `internal_tags::spatial_metric_rr` and
474 : * its derivative \f$\partial_r \gamma_{rr}\f$ is defined by
475 : * `internal_tags::d_spatial_metric_rr`.
476 : */
477 : template <typename DataType>
478 1 : using neg_half_lapse_cubed_times_d_spatial_metric_rr =
479 : ::Tags::TempScalar<23, DataType>;
480 : };
481 :
482 : /*!
483 : * \brief Buffer for caching computed intermediates and quantities that we do
484 : * not want to recompute across the solution's implementation
485 : *
486 : * \details See `internal_tags` documentation for details on what quantities
487 : * the internal tags represent
488 : */
489 : template <typename DataType, typename Frame = ::Frame::Inertial>
490 1 : using CachedBuffer = CachedTempBuffer<
491 : internal_tags::x_minus_center<DataType, Frame>,
492 : internal_tags::r<DataType>, internal_tags::one_over_r<DataType>,
493 : internal_tags::x_over_r<DataType, Frame>,
494 : internal_tags::m_over_r<DataType>, internal_tags::sqrt_f_0<DataType>,
495 : internal_tags::f_0<DataType>,
496 : internal_tags::two_m_over_m_plus_r<DataType>,
497 : internal_tags::two_m_over_m_plus_r_squared<DataType>,
498 : internal_tags::two_m_over_m_plus_r_cubed<DataType>,
499 : internal_tags::spatial_metric_rr<DataType>,
500 : internal_tags::one_over_spatial_metric_rr<DataType>,
501 : internal_tags::spatial_metric_rr_minus_f_0<DataType>,
502 : internal_tags::d_spatial_metric_rr<DataType>,
503 : internal_tags::d_f_0<DataType>,
504 : internal_tags::d_f_0_times_x_over_r<DataType, Frame>,
505 : internal_tags::f_1<DataType>,
506 : internal_tags::f_1_times_x_over_r<DataType, Frame>,
507 : internal_tags::f_2<DataType>,
508 : internal_tags::f_2_times_xxx_over_r_cubed<DataType, Frame>,
509 : internal_tags::f_3<DataType>, internal_tags::f_4<DataType>,
510 : gr::Tags::Lapse<DataType>,
511 : internal_tags::neg_half_lapse_cubed_times_d_spatial_metric_rr<DataType>,
512 : gr::Tags::Shift<DataType, 3, Frame>, DerivShift<DataType, Frame>,
513 : gr::Tags::SpatialMetric<DataType, 3, Frame>,
514 : DerivSpatialMetric<DataType, Frame>,
515 : ::Tags::dt<gr::Tags::SpatialMetric<DataType, 3, Frame>>,
516 : gr::Tags::DetSpatialMetric<DataType>,
517 : internal_tags::one_over_det_spatial_metric<DataType>>;
518 :
519 : /*!
520 : * \brief Computes the intermediates and quantities that we do not want to
521 : * recompute across the solution's implementation
522 : */
523 : template <typename DataType, typename Frame = ::Frame::Inertial>
524 1 : class IntermediateComputer {
525 : public:
526 0 : using CachedBuffer = HarmonicSchwarzschild::CachedBuffer<DataType, Frame>;
527 :
528 : /*!
529 : * \brief Constructs a computer for spacetime quantities of a given
530 : * `gr::Solutions::HarmonicSchwarzschild` solution at at a specific
531 : * Cartesian position
532 : *
533 : * \param solution the given `gr::Solutions::HarmonicSchwarzschild` solution
534 : * \param x Cartesian coordinates of the position at which to compute
535 : * spacetime quantities
536 : */
537 1 : IntermediateComputer(const HarmonicSchwarzschild& solution,
538 : const tnsr::I<DataType, 3, Frame>& x);
539 :
540 : /*!
541 : * \brief Computes the intermediate defined by
542 : * `internal_tags::x_minus_center`
543 : */
544 1 : void operator()(
545 : gsl::not_null<tnsr::I<DataType, 3, Frame>*> x_minus_center,
546 : gsl::not_null<CachedBuffer*> /*cache*/,
547 : internal_tags::x_minus_center<DataType, Frame> /*meta*/) const;
548 :
549 : /*!
550 : * \brief Computes the radius defined by `internal_tags::r`
551 : */
552 1 : void operator()(gsl::not_null<Scalar<DataType>*> r,
553 : gsl::not_null<CachedBuffer*> cache,
554 : internal_tags::r<DataType> /*meta*/) const;
555 :
556 : /*!
557 : * \brief Computes the intermediate defined by `internal_tags::one_over_r`
558 : */
559 1 : void operator()(gsl::not_null<Scalar<DataType>*> one_over_r,
560 : gsl::not_null<CachedBuffer*> cache,
561 : internal_tags::one_over_r<DataType> /*meta*/) const;
562 :
563 : /*!
564 : * \brief Computes the intermediate defined by `internal_tags::x_over_r`
565 : */
566 1 : void operator()(gsl::not_null<tnsr::I<DataType, 3, Frame>*> x_over_r,
567 : gsl::not_null<CachedBuffer*> cache,
568 : internal_tags::x_over_r<DataType, Frame> /*meta*/) const;
569 :
570 : /*!
571 : * \brief Computes the intermediate defined by `internal_tags::m_over_r`
572 : */
573 1 : void operator()(gsl::not_null<Scalar<DataType>*> m_over_r,
574 : gsl::not_null<CachedBuffer*> cache,
575 : internal_tags::m_over_r<DataType> /*meta*/) const;
576 :
577 : /*!
578 : * \brief Computes the intermediate defined by `internal_tags::sqrt_f_0`
579 : */
580 1 : void operator()(gsl::not_null<Scalar<DataType>*> sqrt_f_0,
581 : gsl::not_null<CachedBuffer*> cache,
582 : internal_tags::sqrt_f_0<DataType> /*meta*/) const;
583 :
584 : /*!
585 : * \brief Computes the intermediate defined by `internal_tags::f_0`
586 : */
587 1 : void operator()(gsl::not_null<Scalar<DataType>*> f_0,
588 : gsl::not_null<CachedBuffer*> cache,
589 : internal_tags::f_0<DataType> /*meta*/) const;
590 :
591 : /*!
592 : * \brief Computes the intermediate defined by
593 : * `internal_tags::two_m_over_m_plus_r`
594 : */
595 1 : void operator()(
596 : gsl::not_null<Scalar<DataType>*> two_m_over_m_plus_r,
597 : gsl::not_null<CachedBuffer*> cache,
598 : internal_tags::two_m_over_m_plus_r<DataType> /*meta*/) const;
599 :
600 : /*!
601 : * \brief Computes the intermediate defined by
602 : * `internal_tags::two_m_over_m_plus_r_squared`
603 : */
604 1 : void operator()(
605 : gsl::not_null<Scalar<DataType>*> two_m_over_m_plus_r_squared,
606 : gsl::not_null<CachedBuffer*> cache,
607 : internal_tags::two_m_over_m_plus_r_squared<DataType> /*meta*/) const;
608 :
609 : /*!
610 : * \brief Computes the intermediate defined by
611 : * `internal_tags::two_m_over_m_plus_r_cubed`
612 : */
613 1 : void operator()(
614 : gsl::not_null<Scalar<DataType>*> two_m_over_m_plus_r_cubed,
615 : gsl::not_null<CachedBuffer*> cache,
616 : internal_tags::two_m_over_m_plus_r_cubed<DataType> /*meta*/) const;
617 :
618 : /*!
619 : * \brief Computes the intermediate defined by
620 : * `internal_tags::spatial_metric_rr`
621 : */
622 1 : void operator()(gsl::not_null<Scalar<DataType>*> spatial_metric_rr,
623 : gsl::not_null<CachedBuffer*> cache,
624 : internal_tags::spatial_metric_rr<DataType> /*meta*/) const;
625 :
626 : /*!
627 : * \brief Computes the intermediate defined by
628 : * `internal_tags::one_over_spatial_metric_rr`
629 : */
630 1 : void operator()(
631 : gsl::not_null<Scalar<DataType>*> one_over_spatial_metric_rr,
632 : gsl::not_null<CachedBuffer*> cache,
633 : internal_tags::one_over_spatial_metric_rr<DataType> /*meta*/) const;
634 :
635 : /*!
636 : * \brief Computes the intermediate defined by
637 : * `internal_tags::spatial_metric_rr_minus_f_0`
638 : */
639 1 : void operator()(
640 : gsl::not_null<Scalar<DataType>*> spatial_metric_rr_minus_f_0,
641 : gsl::not_null<CachedBuffer*> cache,
642 : internal_tags::spatial_metric_rr_minus_f_0<DataType> /*meta*/) const;
643 :
644 : /*!
645 : * \brief Computes the intermediate defined by
646 : * `internal_tags::d_spatial_metric_rr`
647 : */
648 1 : void operator()(
649 : gsl::not_null<Scalar<DataType>*> d_spatial_metric_rr,
650 : gsl::not_null<CachedBuffer*> cache,
651 : internal_tags::d_spatial_metric_rr<DataType> /*meta*/) const;
652 :
653 : /*!
654 : * \brief Computes the intermediate defined by `internal_tags::d_f_0`
655 : */
656 1 : void operator()(gsl::not_null<Scalar<DataType>*> d_f_0,
657 : gsl::not_null<CachedBuffer*> cache,
658 : internal_tags::d_f_0<DataType> /*meta*/) const;
659 :
660 : /*!
661 : * \brief Computes the intermediate defined by
662 : * `internal_tags::d_f_0_times_x_over_r`
663 : */
664 1 : void operator()(
665 : gsl::not_null<tnsr::i<DataType, 3, Frame>*> d_f_0_times_x_over_r,
666 : gsl::not_null<CachedBuffer*> cache,
667 : internal_tags::d_f_0_times_x_over_r<DataType, Frame> /*meta*/) const;
668 :
669 : /*!
670 : * \brief Computes the intermediate defined by `internal_tags::f_1`
671 : */
672 1 : void operator()(gsl::not_null<Scalar<DataType>*> f_1,
673 : gsl::not_null<CachedBuffer*> cache,
674 : internal_tags::f_1<DataType> /*meta*/) const;
675 :
676 : /*!
677 : * \brief Computes the intermediate defined by
678 : * `internal_tags::f_1_times_x_over_r`
679 : */
680 1 : void operator()(
681 : gsl::not_null<tnsr::i<DataType, 3, Frame>*> f_1_times_x_over_r,
682 : gsl::not_null<CachedBuffer*> cache,
683 : internal_tags::f_1_times_x_over_r<DataType, Frame> /*meta*/) const;
684 :
685 : /*!
686 : * \brief Computes the intermediate defined by `internal_tags::f_2`
687 : */
688 1 : void operator()(gsl::not_null<Scalar<DataType>*> f_2,
689 : gsl::not_null<CachedBuffer*> cache,
690 : internal_tags::f_2<DataType> /*meta*/) const;
691 :
692 : /*!
693 : * \brief Computes the intermediate defined by
694 : * `internal_tags::f_2_times_xxx_over_r_cubed`
695 : */
696 1 : void operator()(
697 : gsl::not_null<tnsr::iii<DataType, 3, Frame>*>
698 : f_2_times_xxx_over_r_cubed,
699 : gsl::not_null<CachedBuffer*> cache,
700 : internal_tags::f_2_times_xxx_over_r_cubed<DataType, Frame> /*meta*/)
701 : const;
702 :
703 : /*!
704 : * \brief Computes the intermediate defined by `internal_tags::f_3`
705 : */
706 1 : void operator()(gsl::not_null<Scalar<DataType>*> f_3,
707 : gsl::not_null<CachedBuffer*> cache,
708 : internal_tags::f_3<DataType> /*meta*/) const;
709 :
710 : /*!
711 : * \brief Computes the intermediate defined by `internal_tags::f_4`
712 : */
713 1 : void operator()(gsl::not_null<Scalar<DataType>*> f_4,
714 : gsl::not_null<CachedBuffer*> cache,
715 : internal_tags::f_4<DataType> /*meta*/) const;
716 :
717 : /*!
718 : * \brief Computes the lapse
719 : *
720 : * \details Computed as
721 : *
722 : * \f{align}
723 : * \alpha &= \gamma_{rr}^{-1/2}
724 : * \f}
725 : *
726 : * where \f$\gamma_{rr}\f$ is a component of the spatial metric defined by
727 : * `internal_tags::spatial_metric_rr`.
728 : */
729 1 : void operator()(gsl::not_null<Scalar<DataType>*> lapse,
730 : gsl::not_null<CachedBuffer*> cache,
731 : gr::Tags::Lapse<DataType> /*meta*/) const;
732 :
733 : /*!
734 : * \brief Computes the intermediate defined by
735 : * `internal_tags::neg_half_lapse_cubed_times_d_spatial_metric_rr`
736 : */
737 1 : void operator()(
738 : gsl::not_null<Scalar<DataType>*>
739 : neg_half_lapse_cubed_times_d_spatial_metric_rr,
740 : gsl::not_null<CachedBuffer*> cache,
741 : internal_tags::neg_half_lapse_cubed_times_d_spatial_metric_rr<
742 : DataType> /*meta*/) const;
743 :
744 : /*!
745 : * \brief Computes the shift
746 : *
747 : * \details Computed as
748 : *
749 : * \f{align}
750 : * \beta^i &= \left(\frac{2M}{M+r}\right)^2 \frac{X^i}{r}
751 : * \frac{1}{\gamma_{rr}}
752 : * \f}
753 : *
754 : * where \f$M\f$ is the mass of the black hole, \f$r\f$ is the radius
755 : * defined by `internal_tags::r`, \f$X^i\f$ is defined by
756 : * `internal_tags::x_minus_center`, and \f$\gamma_{rr}\f$ is defined by
757 : * `internal_tags::spatial_metric_rr`.
758 : */
759 1 : void operator()(gsl::not_null<tnsr::I<DataType, 3, Frame>*> shift,
760 : gsl::not_null<CachedBuffer*> cache,
761 : gr::Tags::Shift<DataType, 3, Frame> /*meta*/) const;
762 :
763 : /*!
764 : * \brief Computes the spatial derivative of the shift
765 : *
766 : * \details Computed as
767 : *
768 : * \f{align}
769 : * \partial_k \beta^i &=
770 : * f_4 \frac{X^i}{r} \frac{X_k}{r} + \delta_k^i f_3
771 : * \f}
772 : *
773 : * where \f$r\f$ is the radius defined by `internal_tags::r`, \f$X^i\f$ is
774 : * defined by `internal_tags::x_minus_center`, \f$X_j = X^i \delta_{ij}\f$,
775 : * \f$f_3\f$ is defined by `internal_tags::f_3`, and \f$f_4\f$ is defined by
776 : * `internal_tags::f_4`.
777 : */
778 1 : void operator()(gsl::not_null<tnsr::iJ<DataType, 3, Frame>*> deriv_shift,
779 : gsl::not_null<CachedBuffer*> cache,
780 : DerivShift<DataType, Frame> /*meta*/) const;
781 :
782 : /*!
783 : * \brief Computes the spatial metric
784 : *
785 : * \details Computed as
786 : *
787 : * \f{align}
788 : * \gamma_{ij} &=
789 : * \left(\gamma_{rr} - \left(1+\frac{M}{r}\right)^2\right)
790 : * \frac{X_i}{r} \frac{X_j}{r} +
791 : * \delta_{ij} \left(1+\frac{M}{r}\right)^2
792 : * \f}
793 : *
794 : * where \f$M\f$ is the mass of the black hole, \f$r\f$ is the radius
795 : * defined by `internal_tags::r`, \f$\gamma_{rr}\f$ is defined by
796 : * `internal_tags::spatial_metric_rr`, and \f$X_j = X^i \delta_{ij}\f$ where
797 : * \f$X^i\f$ is defined by `internal_tags::x_minus_center`.
798 : */
799 1 : void operator()(gsl::not_null<tnsr::ii<DataType, 3, Frame>*> spatial_metric,
800 : gsl::not_null<CachedBuffer*> cache,
801 : gr::Tags::SpatialMetric<DataType, 3, Frame> /*meta*/) const;
802 :
803 : /*!
804 : * \brief Computes the spatial derivative of the spatial metric
805 : *
806 : * \details Computed as
807 : *
808 : * \f{align}
809 : * \partial_k \gamma_{ij} &=
810 : * f_2 \frac{X_i}{r} \frac{X_j}{r} \frac{X_k}{r} +
811 : * f_1 \frac{X_j}{r} \delta_{ik} + f_1 \frac{X_i}{r} \delta_{jk} +
812 : * \partial_r f_0 \frac{X_k}{r} \delta_{ij}
813 : * \f}
814 : *
815 : * where \f$r\f$ is the radius defined by `internal_tags::r`,
816 : * \f$\partial_r f_0\f$ is defined by `internal_tags::d_f_0`, \f$f_1\f$ is
817 : * defined by `internal_tags::f_1`, \f$f_2\f$ is defined by
818 : * `internal_tags::f_2`, and \f$X_j = X^i \delta_{ij}\f$ where \f$X^i\f$ is
819 : * defined by `internal_tags::x_minus_center`.
820 : */
821 1 : void operator()(
822 : gsl::not_null<tnsr::ijj<DataType, 3, Frame>*> deriv_spatial_metric,
823 : gsl::not_null<CachedBuffer*> cache,
824 : DerivSpatialMetric<DataType, Frame> /*meta*/) const;
825 :
826 : /*!
827 : * \brief Sets the time derivative of the spatial metric to 0
828 : */
829 1 : void operator()(
830 : gsl::not_null<tnsr::ii<DataType, 3, Frame>*> dt_spatial_metric,
831 : gsl::not_null<CachedBuffer*> cache,
832 : ::Tags::dt<gr::Tags::SpatialMetric<DataType, 3, Frame>> /*meta*/) const;
833 :
834 : /*!
835 : * \brief Computes the determinant of the spatial metric
836 : */
837 1 : void operator()(gsl::not_null<Scalar<DataType>*> det_spatial_metric,
838 : gsl::not_null<CachedBuffer*> cache,
839 : gr::Tags::DetSpatialMetric<DataType> /*meta*/) const;
840 :
841 : /*!
842 : * \brief Computes one over the determinant of the spatial metric
843 : */
844 1 : void operator()(
845 : gsl::not_null<Scalar<DataType>*> one_over_det_spatial_metric,
846 : gsl::not_null<CachedBuffer*> cache,
847 : internal_tags::one_over_det_spatial_metric<DataType> /*meta*/) const;
848 :
849 : private:
850 : /*!
851 : * \brief The harmonic Schwarzschild solution
852 : */
853 1 : const HarmonicSchwarzschild& solution_;
854 : /*!
855 : * \brief Cartesian coordinates of the position at which to compute
856 : * spacetime quantities
857 : */
858 1 : const tnsr::I<DataType, 3, Frame>& x_;
859 : };
860 :
861 : /*!
862 : * \brief Computes and returns spacetime quantities of interest
863 : */
864 : template <typename DataType, typename Frame = ::Frame::Inertial>
865 1 : class IntermediateVars : public CachedBuffer<DataType, Frame> {
866 : public:
867 0 : using CachedBuffer = HarmonicSchwarzschild::CachedBuffer<DataType, Frame>;
868 : using CachedBuffer::CachedBuffer;
869 1 : using CachedBuffer::get_var;
870 :
871 : /*!
872 : * \brief Computes and returns the spatial derivative of the lapse
873 : *
874 : * \details Computed as
875 : *
876 : * \f{align}
877 : * \partial_i \alpha &=
878 : * -\frac{1}{2} \gamma_{rr}^{-3/2}
879 : * \partial_r \gamma_{rr} \frac{X_i}{r}
880 : * \f}
881 : *
882 : * where \f$r\f$ is the radius defined by `internal_tags::r`,
883 : * \f$\gamma_{rr}\f$ is defined by `internal_tags::spatial_metric_rr`, its
884 : * derivative \f$\partial_r \gamma_{rr}\f$ is defined by
885 : * `internal_tags::d_spatial_metric_rr`, and \f$X_j = X^i \delta_{ij}\f$
886 : * where \f$X^i\f$ is defined by `internal_tags::x_minus_center`.
887 : */
888 1 : tnsr::i<DataType, 3, Frame> get_var(
889 : const IntermediateComputer<DataType, Frame>& computer,
890 : DerivLapse<DataType, Frame> /*meta*/);
891 :
892 : /*!
893 : * \brief Returns the time derivative of the lapse, which is 0
894 : */
895 1 : Scalar<DataType> get_var(
896 : const IntermediateComputer<DataType, Frame>& computer,
897 : ::Tags::dt<gr::Tags::Lapse<DataType>> /*meta*/);
898 :
899 : /*!
900 : * \brief Returns the time derivative of the shift, which is 0
901 : */
902 1 : tnsr::I<DataType, 3, Frame> get_var(
903 : const IntermediateComputer<DataType, Frame>& computer,
904 : ::Tags::dt<gr::Tags::Shift<DataType, 3, Frame>> /*meta*/);
905 :
906 : /*!
907 : * \brief Computes and returns the square root of the determinant of the
908 : * spatial metric
909 : */
910 1 : Scalar<DataType> get_var(
911 : const IntermediateComputer<DataType, Frame>& computer,
912 : gr::Tags::SqrtDetSpatialMetric<DataType> /*meta*/);
913 :
914 : /*!
915 : * \brief Computes and returns the inverse spatial metric
916 : */
917 1 : tnsr::II<DataType, 3, Frame> get_var(
918 : const IntermediateComputer<DataType, Frame>& computer,
919 : gr::Tags::InverseSpatialMetric<DataType, 3, Frame> /*meta*/);
920 :
921 : /*!
922 : * \brief Computes and returns the extrinsic curvature
923 : */
924 1 : tnsr::ii<DataType, 3, Frame> get_var(
925 : const IntermediateComputer<DataType, Frame>& computer,
926 : gr::Tags::ExtrinsicCurvature<DataType, 3, Frame> /*meta*/);
927 : };
928 :
929 : private:
930 : /*!
931 : * \brief Mass of the black hole
932 : */
933 1 : double mass_{std::numeric_limits<double>::signaling_NaN()};
934 : /*!
935 : * \brief Center of the black hole
936 : */
937 1 : std::array<double, volume_dim> center_ =
938 : make_array<volume_dim>(std::numeric_limits<double>::signaling_NaN());
939 : };
940 :
941 : /*!
942 : * \brief Return whether two harmonic Schwarzschild solutions are equivalent
943 : */
944 1 : SPECTRE_ALWAYS_INLINE bool operator==(const HarmonicSchwarzschild& lhs,
945 : const HarmonicSchwarzschild& rhs) {
946 : return lhs.mass() == rhs.mass() and lhs.center() == rhs.center();
947 : }
948 :
949 : /*!
950 : * \brief Return whether two harmonic Schwarzschild solutions are not equivalent
951 : */
952 1 : SPECTRE_ALWAYS_INLINE bool operator!=(const HarmonicSchwarzschild& lhs,
953 : const HarmonicSchwarzschild& rhs) {
954 : return not(lhs == rhs);
955 : }
956 : } // namespace Solutions
957 : } // namespace gr
|