Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <limits>
7 : #include <memory>
8 : #include <pup.h>
9 :
10 : #include "DataStructures/Tensor/TypeAliases.hpp"
11 : #include "Evolution/Systems/ForceFree/Tags.hpp"
12 : #include "Options/Options.hpp"
13 : #include "PointwiseFunctions/AnalyticData/AnalyticData.hpp"
14 : #include "PointwiseFunctions/AnalyticSolutions/GeneralRelativity/SphericalKerrSchild.hpp"
15 : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
16 : #include "Utilities/TMPL.hpp"
17 :
18 : /// \cond
19 : class DataVector;
20 : namespace PUP {
21 : class er;
22 : } // namespace PUP
23 : /// \endcond
24 :
25 : namespace ForceFree::AnalyticData {
26 : /*!
27 : * \brief The magnetospheric Wald problem proposed in \cite Komissarov2004
28 : *
29 : * This is an initial value problem that evolves the magnetosphere of a rotating
30 : * black hole. The initial condition is given as same as the exact Wald solution
31 : * \cite Wald1974 (see also documentation of ForceFree::Solutions::ExactWald)
32 : *
33 : * \begin{equation}
34 : * A_\mu = \frac{B_0}{2}(\phi_\mu + 2a t_\mu) ,
35 : * \end{equation}
36 : *
37 : * but electric field is set to zero at $t=0$.
38 : *
39 : * In the cartesian projection of the spherical Kerr-Schild coordinates
40 : * (which we use in the code for representing tensors), initial magnetic fields
41 : * is given as
42 : *
43 : * \begin{align}
44 : * \tilde{B}^{x} &= a B_0 z \left[ (ax-ry) \left\{
45 : * \frac{1}{r^4} + \frac{2M r (r^2-a^2)}{(r^4+a^2z^2)^2} \right\}
46 : * + a M r x \left\{ \frac{r^2-z^2}{r^4(r^4+a^2z^2)}
47 : * - \frac{4(r^2+z^2)}{(r^4+a^2z^2)^2} \right\} \right] \\
48 : * \tilde{B}^{y} &= a B_0 z \left[ (rx+ay) \left\{
49 : * \frac{1}{r^4} + \frac{2M r (r^2-a^2)}{(r^4+a^2z^2)^2} \right\}
50 : * + a M r y \left\{ \frac{r^2-z^2}{r^4(r^4+a^2z^2)}
51 : * - \frac{4(r^2+z^2)}{(r^4+a^2z^2)^2} \right\} \right] \\
52 : * \tilde{B}^{z} &= B_0 \left[
53 : * 1 + \frac{a^2z^2}{r^4} + \frac{M a^2}{r^3}\left\{
54 : * 1 - \frac{z^2(a^2+z^2)(5r^4+a^2z^2)}{(r^4+a^2z^2)^2} \right\} \right] .
55 : * \end{align}
56 : *
57 : * where $M$ and $a$ are mass and (dimensionless) spin of the Kerr black hole,
58 : * $B_0$ is the amplitude of magnetic field, and $r$ is the radial coordinate
59 : * defined in the spherical Kerr-Schild coordinate system (see the documentation
60 : * of gr::Solutions::SphericalKerrSchild). All other variables are set to zero
61 : * at $t=0$.
62 : *
63 : * There is no known exact solution to this problem, but numerical simulations
64 : * \cite Komissarov2004 \cite Paschalidis2013 \cite Etienne2017 report that the
65 : * system converges to a steady state with an equatorial current sheet inside
66 : * the ergosphere.
67 : *
68 : * \note We set $M=1$ and $B_0=1$ in the initial data to fix scales.
69 : *
70 : */
71 1 : class MagnetosphericWald : public evolution::initial_data::InitialData,
72 : public MarkAsAnalyticData {
73 : public:
74 0 : struct Spin {
75 0 : using type = double;
76 0 : static constexpr Options::String help = {
77 : "The dimensionless spin of the Kerr BH"};
78 0 : static type upper_bound() { return 1.0; }
79 0 : static type lower_bound() { return -1.0; }
80 : };
81 :
82 0 : using options = tmpl::list<Spin>;
83 0 : static constexpr Options::String help{
84 : "Magnetospheric Wald initial value problem"};
85 :
86 0 : MagnetosphericWald() = default;
87 0 : MagnetosphericWald(const MagnetosphericWald&) = default;
88 0 : MagnetosphericWald& operator=(const MagnetosphericWald&) = default;
89 0 : MagnetosphericWald(MagnetosphericWald&&) = default;
90 0 : MagnetosphericWald& operator=(MagnetosphericWald&&) = default;
91 0 : ~MagnetosphericWald() override = default;
92 :
93 0 : explicit MagnetosphericWald(double spin,
94 : const Options::Context& context = {});
95 :
96 0 : auto get_clone() const
97 : -> std::unique_ptr<evolution::initial_data::InitialData> override;
98 :
99 : /// \cond
100 : explicit MagnetosphericWald(CkMigrateMessage* msg);
101 : using PUP::able::register_constructor;
102 : WRAPPED_PUPable_decl_template(MagnetosphericWald);
103 : /// \endcond
104 :
105 : // NOLINTNEXTLINE(google-runtime-references)
106 0 : void pup(PUP::er& p) override;
107 :
108 : /// @{
109 : /// Retrieve the EM variables at (x,t).
110 1 : static auto variables(const tnsr::I<DataVector, 3>& x,
111 : tmpl::list<Tags::TildeE> /*meta*/)
112 : -> tuples::TaggedTuple<Tags::TildeE>;
113 :
114 1 : auto variables(const tnsr::I<DataVector, 3>& x,
115 : tmpl::list<Tags::TildeB> /*meta*/) const
116 : -> tuples::TaggedTuple<Tags::TildeB>;
117 :
118 1 : static auto variables(const tnsr::I<DataVector, 3>& x,
119 : tmpl::list<Tags::TildePsi> /*meta*/)
120 : -> tuples::TaggedTuple<Tags::TildePsi>;
121 :
122 1 : static auto variables(const tnsr::I<DataVector, 3>& x,
123 : tmpl::list<Tags::TildePhi> /*meta*/)
124 : -> tuples::TaggedTuple<Tags::TildePhi>;
125 :
126 1 : static auto variables(const tnsr::I<DataVector, 3>& x,
127 : tmpl::list<Tags::TildeQ> /*meta*/)
128 : -> tuples::TaggedTuple<Tags::TildeQ>;
129 : /// @}
130 :
131 : /// Retrieve a collection of EM variables at position x
132 : template <typename... Tags>
133 1 : tuples::TaggedTuple<Tags...> variables(const tnsr::I<DataVector, 3>& x,
134 : tmpl::list<Tags...> /*meta*/) const {
135 : static_assert(sizeof...(Tags) > 1,
136 : "The generic template will recurse infinitely if only one "
137 : "tag is being retrieved.");
138 : return {get<Tags>(variables(x, tmpl::list<Tags>{}))...};
139 : }
140 :
141 : /// Retrieve the metric variables
142 : template <typename Tag>
143 1 : tuples::TaggedTuple<Tag> variables(const tnsr::I<DataVector, 3>& x,
144 : tmpl::list<Tag> /*meta*/) const {
145 : constexpr double dummy_time = 0.0;
146 : return background_spacetime_.variables(x, dummy_time, tmpl::list<Tag>{});
147 : }
148 :
149 : private:
150 0 : double spin_ = std::numeric_limits<double>::signaling_NaN();
151 0 : gr::Solutions::SphericalKerrSchild background_spacetime_{};
152 :
153 0 : friend bool operator==(const MagnetosphericWald& lhs,
154 : const MagnetosphericWald& rhs);
155 : };
156 :
157 0 : bool operator!=(const MagnetosphericWald& lhs, const MagnetosphericWald& rhs);
158 :
159 : } // namespace ForceFree::AnalyticData
|