Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 :
8 : #include "DataStructures/DataBox/DataBox.hpp"
9 : #include "DataStructures/DataVector.hpp"
10 : #include "DataStructures/Tensor/Tensor.hpp"
11 : #include "Evolution/Systems/Cce/Initialize/InitializeJ.hpp"
12 : #include "Evolution/Systems/Cce/Initialize/InverseCubic.hpp"
13 : #include "Evolution/Systems/Cce/Tags.hpp"
14 : #include "Evolution/Systems/GeneralizedHarmonic/Tags.hpp"
15 : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp"
16 : #include "NumericalAlgorithms/Spectral/SwshCollocation.hpp"
17 : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp"
18 : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
19 : #include "Utilities/Gsl.hpp"
20 : #include "Utilities/Serialization/CharmPupable.hpp"
21 : #include "Utilities/SetNumberOfGridPoints.hpp"
22 : #include "Utilities/TMPL.hpp"
23 : #include "Utilities/TaggedTuple.hpp"
24 :
25 : namespace Cce {
26 : /// Analytic solutions for CCE worldtube data and corresponding waveform News
27 : namespace Solutions {
28 :
29 : /// \cond
30 : class BouncingBlackHole;
31 : class GaugeWave;
32 : class LinearizedBondiSachs;
33 : class RobinsonTrautman;
34 : class RotatingSchwarzschild;
35 : class TeukolskyWave;
36 : /// \endcond
37 :
38 : /*!
39 : * \brief Abstract base class for analytic worldtube data for verifying the CCE
40 : * system.
41 : *
42 : * \details All of the boundary data quantities are provided by the
43 : * `WorldtubeData::variables()` function.
44 : *
45 : * This class provides caching and conversion between different
46 : * representations of the metric data needed for the worldtube computation and
47 : * evolution. The set of pure virtual functions (required to be overriden in the
48 : * derived classes) is:
49 : * - `WorldtubeData::get_clone()`: should return a
50 : * `std::unique_ptr<WorldtubeData>` with cloned state
51 : * - `WorldtubeData::variables_impl()` (a `protected` function): should compute
52 : * and return by `not_null` pointer the spacetime metric quantity requested in
53 : * the final (metavariable) tag argument. The function overloads that are
54 : * required to be overriden in the derived class are
55 : * `gr::Tags::SpacetimeMetric<DataVector, 3>`,
56 : * `::Tags::dt<gr::Tags::SpacetimeMetric<DataVector, 3>>`,
57 : * `gh::Tags::Phi<DataVector, 3>`, and
58 : * `Cce::Tags::News`.
59 : * - `prepare_solution()`: Any initial precomputation needed to determine all of
60 : * the solutions efficiently. This function is called by the base class prior to
61 : * computing or retrieving from the internal cache the requested quantities.
62 : *
63 : * \warning This class is not intended to be threadsafe! Therefore, using
64 : * instances of this class placed into the const global cache results in
65 : * undefined behavior. The analytic data for CCE is not easily represented as a
66 : * full closed-form solution for the entire Bondi-Sachs-like metric over the
67 : * domain, so this class and its descendants perform numerical calculations such
68 : * as spin-weighted derivatives over the sphere. Instead, it makes best sense to
69 : * compute the global solution over the extraction sphere, and cache
70 : * intermediate steps to avoid repeating potentially expensive tensor
71 : * calculations.
72 : */
73 1 : struct WorldtubeData : public PUP::able {
74 0 : using creatable_classes =
75 : tmpl::list<BouncingBlackHole, GaugeWave, LinearizedBondiSachs,
76 : RobinsonTrautman, RotatingSchwarzschild, TeukolskyWave>;
77 :
78 : /// The set of available tags provided by the analytic solution
79 1 : using tags = tmpl::list<
80 : Tags::CauchyCartesianCoords, Tags::Dr<Tags::CauchyCartesianCoords>,
81 : gr::Tags::SpacetimeMetric<DataVector, 3>,
82 : ::Tags::dt<gr::Tags::SpacetimeMetric<DataVector, 3>>,
83 : gh::Tags::Pi<DataVector, 3>, gh::Tags::Phi<DataVector, 3>,
84 : gr::Tags::SpatialMetric<DataVector, 3>,
85 : ::Tags::dt<gr::Tags::SpatialMetric<DataVector, 3>>,
86 : Tags::Dr<gr::Tags::SpatialMetric<DataVector, 3>>,
87 : gr::Tags::Shift<DataVector, 3>,
88 : ::Tags::dt<gr::Tags::Shift<DataVector, 3>>,
89 : Tags::Dr<gr::Tags::Shift<DataVector, 3>>, gr::Tags::Lapse<DataVector>,
90 : ::Tags::dt<gr::Tags::Lapse<DataVector>>,
91 : Tags::Dr<gr::Tags::Lapse<DataVector>>, Tags::News>;
92 :
93 0 : WRAPPED_PUPable_abstract(WorldtubeData); // NOLINT
94 :
95 : // clang doesn't manage to use = default correctly in this case
96 : // NOLINTNEXTLINE(modernize-use-equals-default)
97 0 : WorldtubeData() {}
98 :
99 0 : explicit WorldtubeData(const double extraction_radius)
100 : : extraction_radius_{extraction_radius} {}
101 :
102 0 : explicit WorldtubeData(CkMigrateMessage* msg) : PUP::able(msg) {}
103 :
104 0 : ~WorldtubeData() override = default;
105 :
106 0 : virtual std::unique_ptr<WorldtubeData> get_clone() const = 0;
107 :
108 : /*!
109 : * \brief Retrieve worldtube data represented by the analytic solution, at
110 : * boundary angular resolution `l_max` and time `time`
111 : *
112 : * \details The set of requested tags are specified by the final argument,
113 : * which must be a `tmpl::list` of tags to be retrieved. The set of available
114 : * tags is found in `WorldtubeData::tags`, and includes coordinate and
115 : * Jacobian quantities as well as metric quantities and derivatives thereof.
116 : */
117 : template <typename... Tags>
118 1 : tuples::TaggedTuple<Tags...> variables(
119 : // NOLINTNEXTLINE(readability-avoid-const-params-in-decls)
120 : const size_t output_l_max, const double time,
121 : tmpl::list<Tags...> /*meta*/) const {
122 : prepare_solution(output_l_max, time);
123 : return {cache_or_compute<Tags>(output_l_max, time)...};
124 : }
125 :
126 0 : void pup(PUP::er& p) override;
127 :
128 : virtual std::unique_ptr<Cce::InitializeJ::InitializeJ<false>>
129 0 : get_initialize_j(const double /*start_time*/) const {
130 : return std::make_unique<Cce::InitializeJ::InverseCubic<false>>();
131 : };
132 :
133 0 : virtual bool use_noninertial_news() const { return false; }
134 :
135 : protected:
136 : template <typename Tag>
137 0 : const auto& cache_or_compute(const size_t output_l_max,
138 : const double time) const {
139 : auto& item_cache = get<IntermediateCacheTag<Tag>>(intermediate_cache_);
140 : if (item_cache.l_max == output_l_max and item_cache.time == time) {
141 : return item_cache.data;
142 : }
143 : auto& item = item_cache.data;
144 : set_number_of_grid_points(
145 : make_not_null(&item),
146 : Spectral::Swsh::number_of_swsh_collocation_points(output_l_max));
147 : variables_impl(make_not_null(&item), output_l_max, time,
148 : tmpl::type_<Tag>{});
149 : item_cache.l_max = output_l_max;
150 : item_cache.time = time;
151 : return item;
152 : }
153 0 : virtual void prepare_solution(size_t output_l_max, double time) const = 0;
154 :
155 : // note that function template cannot be virtual, so we have to emulate
156 : // template specializations through function overloads
157 0 : virtual void variables_impl(
158 : gsl::not_null<tnsr::i<DataVector, 3>*> cartesian_coordinates,
159 : size_t output_l_max, double time,
160 : tmpl::type_<Tags::CauchyCartesianCoords> /*meta*/) const;
161 :
162 0 : virtual void variables_impl(
163 : gsl::not_null<tnsr::i<DataVector, 3>*> dr_cartesian_coordinates,
164 : size_t output_l_max, double time,
165 : tmpl::type_<Tags::Dr<Tags::CauchyCartesianCoords>> /*meta*/) const;
166 :
167 0 : virtual void variables_impl(
168 : gsl::not_null<tnsr::aa<DataVector, 3>*> spacetime_metric,
169 : size_t output_l_max, double time,
170 : tmpl::type_<gr::Tags::SpacetimeMetric<DataVector, 3>>
171 : /*meta*/) const = 0;
172 :
173 0 : virtual void variables_impl(
174 : gsl::not_null<tnsr::aa<DataVector, 3>*> dt_spacetime_metric,
175 : size_t output_l_max, double time,
176 : tmpl::type_<::Tags::dt<gr::Tags::SpacetimeMetric<DataVector, 3>>>
177 : /*meta*/) const = 0;
178 :
179 0 : virtual void variables_impl(gsl::not_null<tnsr::aa<DataVector, 3>*> pi,
180 : size_t output_l_max, double time,
181 : tmpl::type_<gh::Tags::Pi<DataVector, 3>>
182 : /*meta*/) const;
183 :
184 0 : virtual void variables_impl(
185 : gsl::not_null<tnsr::iaa<DataVector, 3>*> d_spacetime_metric,
186 : size_t output_l_max, double time,
187 : tmpl::type_<gh::Tags::Phi<DataVector, 3>>
188 : /*meta*/) const = 0;
189 :
190 0 : virtual void variables_impl(
191 : gsl::not_null<tnsr::ii<DataVector, 3>*> spatial_metric,
192 : size_t output_l_max, double time,
193 : tmpl::type_<gr::Tags::SpatialMetric<DataVector, 3>>
194 : /*meta*/) const;
195 :
196 0 : virtual void variables_impl(
197 : gsl::not_null<tnsr::ii<DataVector, 3>*> dt_spatial_metric,
198 : size_t output_l_max, double time,
199 : tmpl::type_<::Tags::dt<gr::Tags::SpatialMetric<DataVector, 3>>>
200 : /*meta*/) const;
201 :
202 0 : virtual void variables_impl(
203 : gsl::not_null<tnsr::ii<DataVector, 3>*> dr_spatial_metric,
204 : size_t output_l_max, double time,
205 : tmpl::type_<Tags::Dr<gr::Tags::SpatialMetric<DataVector, 3>>>
206 : /*meta*/) const;
207 :
208 0 : virtual void variables_impl(gsl::not_null<tnsr::I<DataVector, 3>*> shift,
209 : size_t output_l_max, double time,
210 : tmpl::type_<gr::Tags::Shift<DataVector, 3>>
211 : /*meta*/) const;
212 :
213 0 : virtual void variables_impl(
214 : gsl::not_null<tnsr::I<DataVector, 3>*> dt_shift, size_t output_l_max,
215 : double time, tmpl::type_<::Tags::dt<gr::Tags::Shift<DataVector, 3>>>
216 : /*meta*/) const;
217 :
218 0 : virtual void variables_impl(
219 : gsl::not_null<tnsr::I<DataVector, 3>*> dr_shift, size_t output_l_max,
220 : double time, tmpl::type_<Tags::Dr<gr::Tags::Shift<DataVector, 3>>>
221 : /*meta*/) const;
222 :
223 0 : virtual void variables_impl(gsl::not_null<Scalar<DataVector>*> lapse,
224 : size_t output_l_max, double time,
225 : tmpl::type_<gr::Tags::Lapse<DataVector>>
226 : /*meta*/) const;
227 :
228 0 : virtual void variables_impl(
229 : gsl::not_null<Scalar<DataVector>*> dt_lapse, size_t output_l_max,
230 : double time, tmpl::type_<::Tags::dt<gr::Tags::Lapse<DataVector>>>
231 : /*meta*/) const;
232 :
233 0 : virtual void variables_impl(gsl::not_null<Scalar<DataVector>*> dr_lapse,
234 : size_t output_l_max, double time,
235 : tmpl::type_<Tags::Dr<gr::Tags::Lapse<DataVector>>>
236 : /*meta*/) const;
237 :
238 0 : virtual void variables_impl(
239 : gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, -2>>*> news,
240 : size_t output_l_max, double time,
241 : tmpl::type_<Tags::News> /*meta*/) const = 0;
242 :
243 : template <typename Tag>
244 0 : struct IntermediateCache {
245 0 : typename Tag::type data;
246 0 : size_t l_max = 0;
247 0 : double time = -std::numeric_limits<double>::infinity();
248 : };
249 :
250 : template <typename Tag>
251 0 : struct IntermediateCacheTag {
252 0 : using type = IntermediateCache<Tag>;
253 : };
254 :
255 0 : using IntermediateCacheTuple =
256 : tuples::tagged_tuple_from_typelist<tmpl::transform<
257 : tmpl::list<Tags::CauchyCartesianCoords,
258 : Tags::Dr<Tags::CauchyCartesianCoords>,
259 : gr::Tags::SpacetimeMetric<DataVector, 3>,
260 : gh::Tags::Pi<DataVector, 3>, gh::Tags::Phi<DataVector, 3>,
261 : gr::Tags::SpatialMetric<DataVector, 3>,
262 : gr::Tags::Shift<DataVector, 3>,
263 : gr::Tags::Lapse<DataVector>,
264 : ::Tags::dt<gr::Tags::SpacetimeMetric<DataVector, 3>>,
265 : ::Tags::dt<gr::Tags::SpatialMetric<DataVector, 3>>,
266 : ::Tags::dt<gr::Tags::Shift<DataVector, 3>>,
267 : ::Tags::dt<gr::Tags::Lapse<DataVector>>,
268 : Tags::Dr<gr::Tags::SpatialMetric<DataVector, 3>>,
269 : Tags::Dr<gr::Tags::Shift<DataVector, 3>>,
270 : Tags::Dr<gr::Tags::Lapse<DataVector>>, Tags::News>,
271 : tmpl::bind<IntermediateCacheTag, tmpl::_1>>>;
272 :
273 : // NOLINTNEXTLINE(spectre-mutable)
274 0 : mutable IntermediateCacheTuple intermediate_cache_;
275 0 : double extraction_radius_ = std::numeric_limits<double>::quiet_NaN();
276 : };
277 : } // namespace Solutions
278 : } // namespace Cce
|