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 <string>
9 :
10 : #include "DataStructures/Tensor/TypeAliases.hpp"
11 : #include "Evolution/Systems/CurvedScalarWave/Tags.hpp"
12 : #include "Options/String.hpp"
13 : #include "PointwiseFunctions/AnalyticData/AnalyticData.hpp"
14 : #include "PointwiseFunctions/AnalyticData/ScalarTensor/AnalyticData.hpp"
15 : #include "PointwiseFunctions/AnalyticSolutions/GeneralRelativity/KerrSchild.hpp"
16 : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
17 : #include "Utilities/Serialization/CharmPupable.hpp"
18 : #include "Utilities/TMPL.hpp"
19 : #include "Utilities/TaggedTuple.hpp"
20 :
21 : /// \cond
22 : namespace PUP {
23 : class er;
24 : } // namespace PUP
25 : /// \endcond
26 :
27 : namespace ScalarTensor::AnalyticData {
28 : /*!
29 : * \brief Analytic initial data for a pure spherical harmonic in three
30 : * dimensions in a KerrSchild background.
31 : *
32 : * \details The initial data is taken from \cite Scheel2003vs , Eqs. 4.1--4.3,
33 : * and sets the evolved variables of the scalar wave as follows:
34 : *
35 : * \f{align}
36 : * \Psi &= 0 \\
37 : * \Phi_i &= 0 \\
38 : * \Pi &= \Pi_0(r, \theta, \phi) = A e^{- (r - r_0)^2 / w^2} Y_{lm}(\theta,
39 : * \phi), \f}
40 : *
41 : * where \f$A\f$ is the amplitude of the profile, \f$r_0\f$ is its radius and
42 : * \f$w\f$ is its width. This describes a pure spherical harmonic mode
43 : * \f$Y_{lm}(\theta, \phi)\f$ truncated by a circular Gaussian window function.
44 : *
45 : * When evolved, the scalar field \f$\Phi\f$ will briefly build up around the
46 : * radius \f$r_0\f$ and then disperse. This can be used to study the ringdown
47 : * behavior and late-time tails in the Kerr spacetime.
48 : * \see CurvedScalarWave::AnalyticData::PureSphericalHarmonic and
49 : * gr::Solutions::KerrSchild.
50 : */
51 1 : class KerrSphericalHarmonic
52 : : public virtual evolution::initial_data::InitialData,
53 : public MarkAsAnalyticData,
54 : public AnalyticDataBase {
55 : public:
56 : /// The mass of the black hole.
57 1 : struct Mass {
58 0 : using type = double;
59 0 : static constexpr Options::String help = {"Mass of the black hole."};
60 0 : static type lower_bound() { return 0.0; }
61 : };
62 : /// The spin of the black hole
63 1 : struct Spin {
64 0 : using type = std::array<double, volume_dim>;
65 0 : static constexpr Options::String help = {
66 : "The [x,y,z] dimensionless spin of the black hole"};
67 : };
68 : /// The amplitude of the scalar field
69 1 : struct Amplitude {
70 0 : using type = double;
71 0 : static constexpr Options::String help = {
72 : "Amplitude of the constant scalar field"};
73 : };
74 : /// The location of the scalar field
75 1 : struct Radius {
76 0 : using type = double;
77 0 : static constexpr Options::String help = {
78 : "The radius of the spherical harmonic profile"};
79 0 : static type lower_bound() { return 0.0; }
80 : };
81 : /// The width of the scalar field
82 1 : struct Width {
83 0 : using type = double;
84 0 : static constexpr Options::String help = {
85 : "The width of the spherical harmonic profile. The width must be "
86 : "greater than 0."};
87 0 : static type lower_bound() { return 0.0; }
88 : };
89 : /// The spherical harmonic mode of the scalar field
90 1 : struct Mode {
91 0 : using type = std::pair<size_t, int>;
92 0 : static constexpr Options::String help = {
93 : "The l-mode and m-mode of the spherical harmonic Ylm. The absolute "
94 : "value of the m_mode must be less than or equal to the "
95 : "l-mode."};
96 : };
97 :
98 0 : using options = tmpl::list<Mass, Spin, Amplitude, Radius, Width, Mode>;
99 0 : static constexpr Options::String help = {
100 : "Initial data for a pure spherical harmonic mode truncated by a circular "
101 : "Gaussian window funtion. The expression is taken from Scheel(2003), "
102 : "equations 4.1-4.3."};
103 :
104 0 : KerrSphericalHarmonic() = default;
105 0 : KerrSphericalHarmonic(const KerrSphericalHarmonic& /*rhs*/) = default;
106 0 : KerrSphericalHarmonic& operator=(const KerrSphericalHarmonic& /*rhs*/) =
107 : default;
108 0 : KerrSphericalHarmonic(KerrSphericalHarmonic&& /*rhs*/) = default;
109 0 : KerrSphericalHarmonic& operator=(KerrSphericalHarmonic&& /*rhs*/) = default;
110 0 : ~KerrSphericalHarmonic() override = default;
111 :
112 0 : KerrSphericalHarmonic(double mass,
113 : const std::array<double, 3>& dimensionless_spin,
114 : double amplitude, double radius, double width,
115 : std::pair<size_t, int> mode);
116 :
117 0 : auto get_clone() const
118 : -> std::unique_ptr<evolution::initial_data::InitialData> override;
119 :
120 : /// \cond
121 : explicit KerrSphericalHarmonic(CkMigrateMessage* msg);
122 : using PUP::able::register_constructor;
123 : WRAPPED_PUPable_decl_template(KerrSphericalHarmonic);
124 : /// \endcond
125 :
126 : // The extra tags below can also be added as common to all scalar tensor
127 : // solutions
128 : template <typename DataType, typename Frame = Frame::Inertial>
129 0 : using tags = tmpl::flatten<tmpl::list<
130 : typename AnalyticDataBase::template tags<DataType>,
131 : gr::Tags::DerivDetSpatialMetric<DataType, 3, Frame>,
132 : gr::Tags::TraceExtrinsicCurvature<DataType>,
133 : gr::Tags::SpatialChristoffelFirstKind<DataType, 3, Frame>,
134 : gr::Tags::SpatialChristoffelSecondKind<DataType, 3, Frame>,
135 : gr::Tags::TraceSpatialChristoffelSecondKind<DataType, 3, Frame>>>;
136 :
137 : /// @{
138 : /// Retrieve scalar variable at `x`
139 : template <typename DataType>
140 1 : auto variables(const tnsr::I<DataType, 3>& x,
141 : tmpl::list<CurvedScalarWave::Tags::Psi> /*meta*/) const
142 : -> tuples::TaggedTuple<CurvedScalarWave::Tags::Psi>;
143 :
144 : template <typename DataType>
145 1 : auto variables(const tnsr::I<DataType, 3>& x,
146 : tmpl::list<CurvedScalarWave::Tags::Phi<3_st>> /*meta*/) const
147 : -> tuples::TaggedTuple<CurvedScalarWave::Tags::Phi<3_st>>;
148 :
149 : template <typename DataType>
150 1 : auto variables(const tnsr::I<DataType, 3>& x,
151 : tmpl::list<CurvedScalarWave::Tags::Pi> /*meta*/) const
152 : -> tuples::TaggedTuple<CurvedScalarWave::Tags::Pi>;
153 : /// @}
154 :
155 : /// Retrieve a collection of scalar variables at `x`
156 : template <typename DataType, typename... Tags>
157 1 : tuples::TaggedTuple<Tags...> variables(const tnsr::I<DataType, 3>& x,
158 : tmpl::list<Tags...> /*meta*/) const {
159 : static_assert(sizeof...(Tags) > 1,
160 : "The generic template will recurse infinitely if only one "
161 : "tag is being retrieved.");
162 : return {get<Tags>(variables(x, tmpl::list<Tags>{}))...};
163 : }
164 :
165 : /// Retrieve the metric variables
166 : template <typename DataType, typename Tag>
167 1 : tuples::TaggedTuple<Tag> variables(
168 : const tnsr::I<DataType, 3>& x,
169 : tmpl::list<Tag> /*meta*/) const {
170 : // We need to provide a time argument for the background solution
171 : return background_spacetime_.variables(x, 0.0, tmpl::list<Tag>{});
172 : }
173 :
174 : // NOLINTNEXTLINE(google-runtime-references)
175 0 : void pup(PUP::er& /*p*/) override;
176 :
177 : protected:
178 0 : friend bool operator==(const KerrSphericalHarmonic& lhs,
179 : const KerrSphericalHarmonic& rhs);
180 :
181 0 : double mass_ = std::numeric_limits<double>::signaling_NaN();
182 0 : std::array<double, volume_dim> dimensionless_spin_ =
183 : make_array<volume_dim>(std::numeric_limits<double>::signaling_NaN());
184 0 : double amplitude_ = std::numeric_limits<double>::signaling_NaN();
185 0 : double radius_{std::numeric_limits<double>::signaling_NaN()};
186 0 : double width_sq_{std::numeric_limits<double>::signaling_NaN()};
187 0 : std::pair<size_t, int> mode_{std::numeric_limits<size_t>::signaling_NaN(),
188 : std::numeric_limits<int>::signaling_NaN()};
189 :
190 0 : gr::Solutions::KerrSchild background_spacetime_{};
191 : };
192 :
193 0 : bool operator!=(const KerrSphericalHarmonic& lhs,
194 : const KerrSphericalHarmonic& rhs);
195 :
196 : } // namespace ScalarTensor::AnalyticData
|