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/ComplexDataVector.hpp"
9 : #include "DataStructures/DataBox/DataBox.hpp"
10 : #include "DataStructures/DataVector.hpp"
11 : #include "DataStructures/SpinWeighted.hpp"
12 : #include "DataStructures/Tags/TempTensor.hpp"
13 : #include "DataStructures/Tensor/EagerMath/DeterminantAndInverse.hpp"
14 : #include "DataStructures/Tensor/TypeAliases.hpp"
15 : #include "DataStructures/Variables.hpp"
16 : #include "Evolution/Systems/Cce/BoundaryData.hpp"
17 : #include "Evolution/Systems/Cce/BoundaryDataTags.hpp"
18 : #include "Evolution/Systems/Cce/Tags.hpp"
19 : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshCollocation.hpp"
20 : #include "NumericalAlgorithms/SpinWeightedSphericalHarmonics/SwshDerivatives.hpp"
21 : #include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/Phi.hpp"
22 : #include "PointwiseFunctions/GeneralRelativity/SpacetimeMetric.hpp"
23 : #include "PointwiseFunctions/GeneralRelativity/TimeDerivativeOfSpacetimeMetric.hpp"
24 : #include "Utilities/Gsl.hpp"
25 :
26 : namespace Cce {
27 : /*
28 : * \brief Compute \f$\gamma_{i j}\f$, \f$\gamma^{i j}\f$,
29 : * \f$\partial_i \gamma_{j k}\f$, and
30 : * \f$\partial_t g_{i j}\f$ from input libsharp-compatible modal spatial
31 : * metric quantities.
32 : *
33 : * \details This function will apply a correction factor associated with a SpEC
34 : * bug.
35 : */
36 0 : void cartesian_spatial_metric_and_derivatives_from_unnormalized_spec_modes(
37 : gsl::not_null<tnsr::ii<DataVector, 3>*> cartesian_spatial_metric,
38 : gsl::not_null<tnsr::II<DataVector, 3>*> inverse_cartesian_spatial_metric,
39 : gsl::not_null<tnsr::ijj<DataVector, 3>*> d_cartesian_spatial_metric,
40 : gsl::not_null<tnsr::ii<DataVector, 3>*> dt_cartesian_spatial_metric,
41 : gsl::not_null<Scalar<SpinWeighted<ComplexModalVector, 0>>*>
42 : interpolation_modal_buffer,
43 : gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
44 : interpolation_buffer,
45 : gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*> eth_buffer,
46 : gsl::not_null<Scalar<DataVector>*> radial_correction_factor,
47 : const tnsr::ii<ComplexModalVector, 3>& spatial_metric_coefficients,
48 : const tnsr::ii<ComplexModalVector, 3>& dr_spatial_metric_coefficients,
49 : const tnsr::ii<ComplexModalVector, 3>& dt_spatial_metric_coefficients,
50 : const CartesianiSphericalJ& inverse_cartesian_to_spherical_jacobian,
51 : const tnsr::I<DataVector, 3>& unit_cartesian_coords, size_t l_max);
52 :
53 : /*!
54 : * \brief Compute \f$\beta^{i}\f$, \f$\partial_i \beta^{j}\f$, and
55 : * \f$\partial_t \beta^i\f$ from input libsharp-compatible modal spatial
56 : * metric quantities.
57 : *
58 : * \details This function will apply a correction factor associated with a SpEC
59 : * bug.
60 : */
61 1 : void cartesian_shift_and_derivatives_from_unnormalized_spec_modes(
62 : gsl::not_null<tnsr::I<DataVector, 3>*> cartesian_shift,
63 : gsl::not_null<tnsr::iJ<DataVector, 3>*> d_cartesian_shift,
64 : gsl::not_null<tnsr::I<DataVector, 3>*> dt_cartesian_shift,
65 : gsl::not_null<Scalar<SpinWeighted<ComplexModalVector, 0>>*>
66 : interpolation_modal_buffer,
67 : gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
68 : interpolation_buffer,
69 : gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*> eth_buffer,
70 : const tnsr::I<ComplexModalVector, 3>& shift_coefficients,
71 : const tnsr::I<ComplexModalVector, 3>& dr_shift_coefficients,
72 : const tnsr::I<ComplexModalVector, 3>& dt_shift_coefficients,
73 : const CartesianiSphericalJ& inverse_cartesian_to_spherical_jacobian,
74 : const Scalar<DataVector>& radial_derivative_correction_factor,
75 : size_t l_max);
76 :
77 : /*!
78 : * \brief Compute \f$\alpha\f$, \f$\partial_i \alpha\f$, and
79 : * \f$\partial_t \beta^i\f$ from input libsharp-compatible modal spatial
80 : * metric quantities.
81 : *
82 : * \details This function will apply a correction factor associated with a SpEC
83 : * bug.
84 : */
85 1 : void cartesian_lapse_and_derivatives_from_unnormalized_spec_modes(
86 : gsl::not_null<Scalar<DataVector>*> cartesian_lapse,
87 : gsl::not_null<tnsr::i<DataVector, 3>*> d_cartesian_lapse,
88 : gsl::not_null<Scalar<DataVector>*> dt_cartesian_lapse,
89 : gsl::not_null<Scalar<SpinWeighted<ComplexModalVector, 0>>*>
90 : interpolation_modal_buffer,
91 : gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 0>>*>
92 : interpolation_buffer,
93 : gsl::not_null<Scalar<SpinWeighted<ComplexDataVector, 1>>*> eth_buffer,
94 : const Scalar<ComplexModalVector>& lapse_coefficients,
95 : const Scalar<ComplexModalVector>& dr_lapse_coefficients,
96 : const Scalar<ComplexModalVector>& dt_lapse_coefficients,
97 : const CartesianiSphericalJ& inverse_cartesian_to_spherical_jacobian,
98 : const Scalar<DataVector>& radial_derivative_correction_factor,
99 : size_t l_max);
100 :
101 : /*!
102 : * \brief Process the worldtube data from modal metric components and
103 : * derivatives with incorrectly normalized radial derivatives from an old
104 : * version of SpEC to desired Bondi quantities, placing the result in the passed
105 : * \ref DataBoxGroup.
106 : *
107 : * \details
108 : * The mathematics are a bit complicated for all of the coordinate
109 : * transformations that are necessary to obtain the Bondi gauge quantities.
110 : * For full mathematical details, see the documentation for functions in
111 : * `BoundaryData.hpp` and \cite Barkett2019uae \cite Bishop1998uk.
112 : *
113 : * This function takes as input the full set of ADM metric data and its radial
114 : * and time derivatives on a two-dimensional surface of constant \f$r\f$ and
115 : * \f$t\f$ in numerical coordinates. This data must be provided as spherical
116 : * harmonic coefficients in the libsharp format. This data is provided in nine
117 : * `Tensor`s.
118 : *
119 : * Sufficient tags to provide full worldtube boundary data at a particular
120 : * time are set in `bondi_boundary_data`. In particular, the set of tags in
121 : * `Tags::characteristic_worldtube_boundary_tags` in the provided \ref
122 : * DataBoxGroup are assigned to the worldtube boundary values associated with
123 : * the input metric components.
124 : *
125 : * The majority of the mathematical transformations are implemented as a set of
126 : * individual cascaded functions below. The details of the manipulations that
127 : * are performed to the input data may be found in the individual functions
128 : * themselves, which are called in the following order:
129 : * - `trigonometric_functions_on_swsh_collocation()`
130 : * - `cartesian_to_spherical_coordinates_and_jacobians()`
131 : * - `cartesian_spatial_metric_and_derivatives_from_unnormalized_spec_modes()`
132 : * - `cartesian_shift_and_derivatives_from_unnormalized_spec_modes()`
133 : * - `cartesian_lapse_and_derivatives_from_unnormalized_spec_modes()`
134 : * - `gh::phi()`
135 : * - `gr::time_derivative_of_spacetime_metric`
136 : * - `gr::spacetime_metric`
137 : * - `generalized_harmonic_quantities()`
138 : * - `worldtube_normal_and_derivatives()`
139 : * - `null_vector_l_and_derivatives()`
140 : * - `null_metric_and_derivative()`
141 : * - `dlambda_null_metric_and_inverse()`
142 : * - `bondi_r()`
143 : * - `d_bondi_r()`
144 : * - `dyads()`
145 : * - `beta_worldtube_data()`
146 : * - `bondi_u_worldtube_data()`
147 : * - `bondi_w_worldtube_data()`
148 : * - `bondi_j_worldtube_data()`
149 : * - `dr_bondi_j()`
150 : * - `d2lambda_bondi_r()`
151 : * - `bondi_q_worldtube_data()`
152 : * - `bondi_h_worldtube_data()`
153 : * - `du_j_worldtube_data()`
154 : */
155 : template <typename TagList>
156 1 : void create_bondi_boundary_data_from_unnormalized_spec_modes(
157 : const gsl::not_null<Variables<TagList>*> bondi_boundary_data,
158 : const tnsr::ii<ComplexModalVector, 3>& spatial_metric_coefficients,
159 : const tnsr::ii<ComplexModalVector, 3>& dt_spatial_metric_coefficients,
160 : const tnsr::ii<ComplexModalVector, 3>& dr_spatial_metric_coefficients,
161 : const tnsr::I<ComplexModalVector, 3>& shift_coefficients,
162 : const tnsr::I<ComplexModalVector, 3>& dt_shift_coefficients,
163 : const tnsr::I<ComplexModalVector, 3>& dr_shift_coefficients,
164 : const Scalar<ComplexModalVector>& lapse_coefficients,
165 : const Scalar<ComplexModalVector>& dt_lapse_coefficients,
166 : const Scalar<ComplexModalVector>& dr_lapse_coefficients,
167 : const double extraction_radius, const size_t l_max) {
168 : const size_t size = Spectral::Swsh::number_of_swsh_collocation_points(l_max);
169 :
170 : // Most allocations required for the full boundary computation are merged into
171 : // a single, large Variables allocation. There remain a handful of cases in
172 : // the computational functions called where an intermediate quantity that is
173 : // not re-used is allocated rather than taking a buffer. These cases are
174 : // marked with code comments 'Allocation'; In future, allocations are
175 : // identified as a point to optimize, those buffers may be allocated here and
176 : // passed as function arguments
177 : Variables<tmpl::list<
178 : Tags::detail::CosPhi, Tags::detail::CosTheta, Tags::detail::SinPhi,
179 : Tags::detail::SinTheta, Tags::detail::CartesianCoordinates,
180 : Tags::detail::CartesianToSphericalJacobian,
181 : Tags::detail::InverseCartesianToSphericalJacobian,
182 : gr::Tags::SpatialMetric<DataVector, 3>,
183 : gr::Tags::InverseSpatialMetric<DataVector, 3>,
184 : ::Tags::deriv<gr::Tags::SpatialMetric<DataVector, 3>, tmpl::size_t<3>,
185 : ::Frame::Inertial>,
186 : ::Tags::dt<gr::Tags::SpatialMetric<DataVector, 3>>,
187 : gr::Tags::Shift<DataVector, 3>,
188 : ::Tags::deriv<gr::Tags::Shift<DataVector, 3>, tmpl::size_t<3>,
189 : ::Frame::Inertial>,
190 : ::Tags::dt<gr::Tags::Shift<DataVector, 3>>, gr::Tags::Lapse<DataVector>,
191 : ::Tags::deriv<gr::Tags::Lapse<DataVector>, tmpl::size_t<3>,
192 : ::Frame::Inertial>,
193 : ::Tags::dt<gr::Tags::Lapse<DataVector>>,
194 : gr::Tags::SpacetimeMetric<DataVector, 3>,
195 : ::Tags::dt<gr::Tags::SpacetimeMetric<DataVector, 3>>,
196 : gh::Tags::Phi<DataVector, 3>, Tags::detail::WorldtubeNormal,
197 : ::Tags::dt<Tags::detail::WorldtubeNormal>, Tags::detail::NullL,
198 : ::Tags::dt<Tags::detail::NullL>,
199 : // for the detail function called at the end
200 : gr::Tags::SpacetimeMetric<DataVector, 3, Frame::RadialNull>,
201 : ::Tags::dt<gr::Tags::SpacetimeMetric<DataVector, 3, Frame::RadialNull>>,
202 : gr::Tags::InverseSpacetimeMetric<DataVector, 3, Frame::RadialNull>,
203 : Tags::detail::AngularDNullL,
204 : Tags::detail::DLambda<
205 : gr::Tags::SpacetimeMetric<DataVector, 3, Frame::RadialNull>>,
206 : Tags::detail::DLambda<
207 : gr::Tags::InverseSpacetimeMetric<DataVector, 3, Frame::RadialNull>>,
208 : ::Tags::spacetime_deriv<Tags::detail::RealBondiR, tmpl::size_t<3>,
209 : Frame::RadialNull>,
210 : Tags::detail::DLambda<Tags::detail::DLambda<Tags::detail::RealBondiR>>,
211 : ::Tags::deriv<Tags::detail::DLambda<Tags::detail::RealBondiR>,
212 : tmpl::size_t<2>, Frame::RadialNull>,
213 : ::Tags::TempScalar<0, DataVector>>>
214 : computation_variables{size};
215 :
216 : Variables<
217 : tmpl::list<::Tags::SpinWeighted<::Tags::TempScalar<0, ComplexDataVector>,
218 : std::integral_constant<int, 0>>,
219 : ::Tags::SpinWeighted<::Tags::TempScalar<0, ComplexDataVector>,
220 : std::integral_constant<int, 1>>>>
221 : derivative_buffers{size};
222 : auto& cos_phi = get<Tags::detail::CosPhi>(computation_variables);
223 : auto& cos_theta = get<Tags::detail::CosTheta>(computation_variables);
224 : auto& sin_phi = get<Tags::detail::SinPhi>(computation_variables);
225 : auto& sin_theta = get<Tags::detail::SinTheta>(computation_variables);
226 : trigonometric_functions_on_swsh_collocation(
227 : make_not_null(&cos_phi), make_not_null(&cos_theta),
228 : make_not_null(&sin_phi), make_not_null(&sin_theta), l_max);
229 :
230 : // NOTE: to handle the singular values of polar coordinates, the phi
231 : // components of all tensors are scaled according to their sin(theta)
232 : // prefactors.
233 : // so, any down-index component get<2>(A) represents 1/sin(theta) A_\phi,
234 : // and any up-index component get<2>(A) represents sin(theta) A^\phi.
235 : // This holds for Jacobians, and so direct application of the Jacobians
236 : // brings the factors through.
237 : auto& cartesian_coords =
238 : get<Tags::detail::CartesianCoordinates>(computation_variables);
239 : auto& cartesian_to_spherical_jacobian =
240 : get<Tags::detail::CartesianToSphericalJacobian>(computation_variables);
241 : auto& inverse_cartesian_to_spherical_jacobian =
242 : get<Tags::detail::InverseCartesianToSphericalJacobian>(
243 : computation_variables);
244 : cartesian_to_spherical_coordinates_and_jacobians(
245 : make_not_null(&cartesian_coords),
246 : make_not_null(&cartesian_to_spherical_jacobian),
247 : make_not_null(&inverse_cartesian_to_spherical_jacobian), cos_phi,
248 : cos_theta, sin_phi, sin_theta, extraction_radius);
249 :
250 : auto& cartesian_spatial_metric =
251 : get<gr::Tags::SpatialMetric<DataVector, 3>>(computation_variables);
252 : auto& inverse_spatial_metric =
253 : get<gr::Tags::InverseSpatialMetric<DataVector, 3>>(computation_variables);
254 : auto& d_cartesian_spatial_metric =
255 : get<::Tags::deriv<gr::Tags::SpatialMetric<DataVector, 3>, tmpl::size_t<3>,
256 : ::Frame::Inertial>>(computation_variables);
257 : auto& dt_cartesian_spatial_metric =
258 : get<::Tags::dt<gr::Tags::SpatialMetric<DataVector, 3>>>(
259 : computation_variables);
260 : auto& interpolation_buffer =
261 : get<::Tags::SpinWeighted<::Tags::TempScalar<0, ComplexDataVector>,
262 : std::integral_constant<int, 0>>>(
263 : derivative_buffers);
264 : Scalar<SpinWeighted<ComplexModalVector, 0>> interpolation_modal_buffer{size};
265 : auto& eth_buffer =
266 : get<::Tags::SpinWeighted<::Tags::TempScalar<0, ComplexDataVector>,
267 : std::integral_constant<int, 1>>>(
268 : derivative_buffers);
269 : auto& radial_correction_factor =
270 : get<::Tags::TempScalar<0, DataVector>>(computation_variables);
271 : cartesian_spatial_metric_and_derivatives_from_unnormalized_spec_modes(
272 : make_not_null(&cartesian_spatial_metric),
273 : make_not_null(&inverse_spatial_metric),
274 : make_not_null(&d_cartesian_spatial_metric),
275 : make_not_null(&dt_cartesian_spatial_metric),
276 : make_not_null(&interpolation_modal_buffer),
277 : make_not_null(&interpolation_buffer), make_not_null(ð_buffer),
278 : make_not_null(&radial_correction_factor), spatial_metric_coefficients,
279 : dr_spatial_metric_coefficients, dt_spatial_metric_coefficients,
280 : inverse_cartesian_to_spherical_jacobian, cartesian_coords, l_max);
281 :
282 : auto& cartesian_shift =
283 : get<gr::Tags::Shift<DataVector, 3>>(computation_variables);
284 : auto& d_cartesian_shift =
285 : get<::Tags::deriv<gr::Tags::Shift<DataVector, 3>, tmpl::size_t<3>,
286 : ::Frame::Inertial>>(computation_variables);
287 : auto& dt_cartesian_shift =
288 : get<::Tags::dt<gr::Tags::Shift<DataVector, 3>>>(computation_variables);
289 :
290 : cartesian_shift_and_derivatives_from_unnormalized_spec_modes(
291 : make_not_null(&cartesian_shift), make_not_null(&d_cartesian_shift),
292 : make_not_null(&dt_cartesian_shift),
293 : make_not_null(&interpolation_modal_buffer),
294 : make_not_null(&interpolation_buffer), make_not_null(ð_buffer),
295 : shift_coefficients, dr_shift_coefficients, dt_shift_coefficients,
296 : inverse_cartesian_to_spherical_jacobian, radial_correction_factor, l_max);
297 :
298 : auto& cartesian_lapse =
299 : get<gr::Tags::Lapse<DataVector>>(computation_variables);
300 : auto& d_cartesian_lapse =
301 : get<::Tags::deriv<gr::Tags::Lapse<DataVector>, tmpl::size_t<3>,
302 : ::Frame::Inertial>>(computation_variables);
303 : auto& dt_cartesian_lapse =
304 : get<::Tags::dt<gr::Tags::Lapse<DataVector>>>(computation_variables);
305 : cartesian_lapse_and_derivatives_from_unnormalized_spec_modes(
306 : make_not_null(&cartesian_lapse), make_not_null(&d_cartesian_lapse),
307 : make_not_null(&dt_cartesian_lapse),
308 : make_not_null(&interpolation_modal_buffer),
309 : make_not_null(&interpolation_buffer), make_not_null(ð_buffer),
310 : lapse_coefficients, dr_lapse_coefficients, dt_lapse_coefficients,
311 : inverse_cartesian_to_spherical_jacobian, radial_correction_factor, l_max);
312 :
313 : auto& phi = get<gh::Tags::Phi<DataVector, 3>>(computation_variables);
314 : auto& dt_spacetime_metric =
315 : get<::Tags::dt<gr::Tags::SpacetimeMetric<DataVector, 3>>>(
316 : computation_variables);
317 : auto& spacetime_metric =
318 : get<gr::Tags::SpacetimeMetric<DataVector, 3>>(computation_variables);
319 : gh::phi(make_not_null(&phi), cartesian_lapse, d_cartesian_lapse,
320 : cartesian_shift, d_cartesian_shift, cartesian_spatial_metric,
321 : d_cartesian_spatial_metric);
322 : gr::time_derivative_of_spacetime_metric(
323 : make_not_null(&dt_spacetime_metric), cartesian_lapse, dt_cartesian_lapse,
324 : cartesian_shift, dt_cartesian_shift, cartesian_spatial_metric,
325 : dt_cartesian_spatial_metric);
326 : gr::spacetime_metric(make_not_null(&spacetime_metric), cartesian_lapse,
327 : cartesian_shift, cartesian_spatial_metric);
328 :
329 : auto& dt_worldtube_normal =
330 : get<::Tags::dt<Tags::detail::WorldtubeNormal>>(computation_variables);
331 : auto& worldtube_normal =
332 : get<Tags::detail::WorldtubeNormal>(computation_variables);
333 : worldtube_normal_and_derivatives(
334 : make_not_null(&worldtube_normal), make_not_null(&dt_worldtube_normal),
335 : cos_phi, cos_theta, spacetime_metric, dt_spacetime_metric, sin_phi,
336 : sin_theta, inverse_spatial_metric);
337 :
338 : auto& du_null_l = get<::Tags::dt<Tags::detail::NullL>>(computation_variables);
339 : auto& null_l = get<Tags::detail::NullL>(computation_variables);
340 : null_vector_l_and_derivatives(
341 : make_not_null(&du_null_l), make_not_null(&null_l), dt_worldtube_normal,
342 : dt_cartesian_lapse, dt_spacetime_metric, dt_cartesian_shift,
343 : cartesian_lapse, spacetime_metric, cartesian_shift, worldtube_normal);
344 :
345 : // pass to the next step that is common between the 'modal' input and 'GH'
346 : // input strategies
347 : detail::create_bondi_boundary_data(
348 : bondi_boundary_data, make_not_null(&computation_variables),
349 : make_not_null(&derivative_buffers), dt_spacetime_metric, phi,
350 : spacetime_metric, null_l, du_null_l, cartesian_to_spherical_jacobian,
351 : l_max, extraction_radius);
352 : }
353 : } // namespace Cce
|