• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sxs-collaboration / spectre / 4257679734

pending completion
4257679734

push

github

GitHub
Merge pull request #4768 from nilsvu/wheeler_py_module

63960 of 66651 relevant lines covered (95.96%)

415528.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.44
/src/Evolution/Systems/GeneralizedHarmonic/GaugeSourceFunctions/DampedHarmonic.cpp
1
// Distributed under the MIT License.
2
// See LICENSE.txt for details.
3

4
#include "Evolution/Systems/GeneralizedHarmonic/GaugeSourceFunctions/DampedHarmonic.hpp"
5

6
#include <array>
7
#include <cmath>
8
#include <cstddef>
9
#include <limits>
10

11
#include "DataStructures/DataVector.hpp"
12
#include "DataStructures/Tags/TempTensor.hpp"
13
#include "DataStructures/TempBuffer.hpp"
14
#include "DataStructures/Tensor/EagerMath/DotProduct.hpp"
15
#include "DataStructures/Tensor/Tensor.hpp"
16
#include "Evolution/Systems/GeneralizedHarmonic/GaugeSourceFunctions/DampedWaveHelpers.hpp"
17
#include "Evolution/Systems/GeneralizedHarmonic/GaugeSourceFunctions/HalfPiPhiTwoNormals.hpp"
18
#include "PointwiseFunctions/GeneralRelativity/DerivativesOfSpacetimeMetric.hpp"
19
#include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/DerivSpatialMetric.hpp"
20
#include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/SpacetimeDerivativeOfSpacetimeMetric.hpp"
21
#include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/SpatialDerivOfLapse.hpp"
22
#include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/SpatialDerivOfShift.hpp"
23
#include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/TimeDerivOfLapse.hpp"
24
#include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/TimeDerivOfShift.hpp"
25
#include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/TimeDerivOfSpatialMetric.hpp"
26
#include "PointwiseFunctions/GeneralRelativity/InverseSpacetimeMetric.hpp"
27
#include "PointwiseFunctions/GeneralRelativity/SpacetimeNormalVector.hpp"
28
#include "PointwiseFunctions/GeneralRelativity/SpatialMetric.hpp"
29
#include "Utilities/ConstantExpressions.hpp"
30
#include "Utilities/ContainerHelpers.hpp"
31
#include "Utilities/GenerateInstantiations.hpp"
32
#include "Utilities/Gsl.hpp"
33
#include "Utilities/TMPL.hpp"
34

35
// IWYU pragma: no_forward_declare Tensor
36

37
namespace GeneralizedHarmonic::gauges {
38
namespace DampedHarmonicGauge_detail {
39
// Roll-on function for the damped harmonic gauge.
40
//
41
// For times after \f$t_0\f$, compute the roll-on function
42
// \f$ R(t) = 1 - \exp(-((t - t_0)/\sigma_t)^4]) \f$,
43
// and return \f$ R(t) = 0\f$ at times before.
44
double roll_on_function(const double time, const double t_start,
9✔
45
                        const double sigma_t) {
46
  if (time < t_start) {
9✔
47
    return 0.;
×
48
  }
49
  return 1. - exp(-pow<4>((time - t_start) / sigma_t));
18✔
50
}
51

52
// Time derivative of the damped harmonic gauge roll-on function.
53
//
54
// \details Compute the time derivative:
55
// \f{align*}
56
// \partial_0 R(t) = 4 exp[-((t - t0)/\sigma_t)^4] (t - t0)^3 / sigma_t^4
57
double time_deriv_of_roll_on_function(const double time, const double t_start,
9✔
58
                                      const double sigma_t) {
59
  if (time < t_start) {
9✔
60
    return 0.;
2✔
61
  }
62
  const double time_since_start_over_sigma = (time - t_start) / sigma_t;
7✔
63
  return exp(-pow<4>(time_since_start_over_sigma)) * 4. *
7✔
64
         pow<3>(time_since_start_over_sigma) / sigma_t;
7✔
65
}
66
}  // namespace DampedHarmonicGauge_detail
67

68
namespace {
69
template <bool UseRollon, size_t SpatialDim, typename Frame>
70
void damped_harmonic_impl(
50✔
71
    const gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame>*> gauge_h,
72
    const gsl::not_null<tnsr::ab<DataVector, SpatialDim, Frame>*> d4_gauge_h,
73
    const tnsr::a<DataVector, SpatialDim, Frame>* gauge_h_init,
74
    const tnsr::ab<DataVector, SpatialDim, Frame>* dgauge_h_init,
75
    const Scalar<DataVector>& lapse,
76
    const tnsr::I<DataVector, SpatialDim, Frame>& shift,
77
    const tnsr::a<DataVector, SpatialDim, Frame>&
78
        spacetime_unit_normal_one_form,
79
    const tnsr::A<DataVector, SpatialDim, Frame>& spacetime_unit_normal,
80
    const Scalar<DataVector>& sqrt_det_spatial_metric,
81
    const tnsr::II<DataVector, SpatialDim, Frame>& inverse_spatial_metric,
82
    const tnsr::abb<DataVector, SpatialDim, Frame>& d4_spacetime_metric,
83
    const Scalar<DataVector>& half_pi_two_normals,
84
    const tnsr::i<DataVector, SpatialDim, Frame>& half_phi_two_normals,
85
    const tnsr::aa<DataVector, SpatialDim, Frame>& spacetime_metric,
86
    const tnsr::aa<DataVector, SpatialDim, Frame>& pi,
87
    const tnsr::iaa<DataVector, SpatialDim, Frame>& phi, const double time,
88
    const tnsr::I<DataVector, SpatialDim, Frame>& coords,
89
    const double amp_coef_L1, const double amp_coef_L2, const double amp_coef_S,
90
    const int exp_L1, const int exp_L2, const int exp_S,
91
    const double rollon_start_time, const double rollon_width,
92
    const double sigma_r) {
93
  const size_t num_points = get(lapse).size();
50✔
94
  destructive_resize_components(gauge_h, num_points);
50✔
95
  destructive_resize_components(d4_gauge_h, num_points);
50✔
96

97
  if constexpr (UseRollon) {
98
    ASSERT(gauge_h_init != nullptr,
3✔
99
           "Cannot call damped_harmonic_impl with UseRollon enabled and "
100
           "gauge_h_init being nullptr");
101
    ASSERT(dgauge_h_init != nullptr,
3✔
102
           "Cannot call damped_harmonic_impl with UseRollon enabled and "
103
           "dgauge_h_init being nullptr");
104
  } else {
105
    ASSERT(gauge_h_init == nullptr,
47✔
106
           "Cannot call damped_harmonic_impl with UseRollon disabled and "
107
           "gauge_h_init not being nullptr");
108
    ASSERT(dgauge_h_init == nullptr,
47✔
109
           "Cannot call damped_harmonic_impl with UseRollon disabled and "
110
           "dgauge_h_init not being nullptr");
111
  }
112

113
  // Use a TempBuffer to reduce total number of allocations. This is especially
114
  // important in a multithreaded environment.
115
  TempBuffer<tmpl::list<
116
      ::Tags::Tempii<1, SpatialDim, Frame>,
117
      ::Tags::Tempijj<4, SpatialDim, Frame>, ::Tags::TempScalar<5>,
118
      ::Tags::TempScalar<6>, ::Tags::TempScalar<7>, ::Tags::TempScalar<8>,
119
      ::Tags::TempScalar<9>, ::Tags::TempScalar<10>, ::Tags::TempScalar<11>,
120
      ::Tags::TempScalar<12>, ::Tags::TempScalar<13>, ::Tags::TempScalar<14>,
121
      ::Tags::Tempa<15, SpatialDim, Frame>,
122
      ::Tags::Tempa<16, SpatialDim, Frame>,
123
      ::Tags::Tempa<17, SpatialDim, Frame>,
124
      ::Tags::Tempa<18, SpatialDim, Frame>,
125
      ::Tags::Tempa<19, SpatialDim, Frame>,
126
      ::Tags::Tempa<20, SpatialDim, Frame>,
127
      ::Tags::Tempa<21, SpatialDim, Frame>,
128
      ::Tags::Tempa<22, SpatialDim, Frame>,
129
      ::Tags::Tempa<23, SpatialDim, Frame>,
130
      ::Tags::Tempa<24, SpatialDim, Frame>,
131
      ::Tags::Tempa<27, SpatialDim, Frame>,
132
      ::Tags::TempaB<30, SpatialDim, Frame>,
133
      ::Tags::Tempa<31, SpatialDim, Frame>, ::Tags::TempScalar<32>,
134
      ::Tags::Tempa<33, SpatialDim, Frame>,
135
      ::Tags::Tempab<35, SpatialDim, Frame>,
136
      ::Tags::Tempa<36, SpatialDim, Frame>,
137
      ::Tags::Tempab<37, SpatialDim, Frame>>>
138
      buffer(num_points);
100✔
139
  auto& one_over_lapse = get<::Tags::TempScalar<5>>(buffer);
50✔
140
  auto& log_fac_1 = get<::Tags::TempScalar<6>>(buffer);
50✔
141
  auto& log_fac_2 = get<::Tags::TempScalar<7>>(buffer);
50✔
142
  auto& weight = get<::Tags::TempScalar<8>>(buffer);
50✔
143
  auto& mu_L1 = get<::Tags::TempScalar<9>>(buffer);
50✔
144
  auto& mu_S = get<::Tags::TempScalar<10>>(buffer);
50✔
145
  auto& mu_L2 = get<::Tags::TempScalar<11>>(buffer);
50✔
146
  auto& mu_S_over_lapse = get<::Tags::TempScalar<12>>(buffer);
50✔
147
  auto& mu1 = get<::Tags::TempScalar<13>>(buffer);
50✔
148
  auto& mu2 = get<::Tags::TempScalar<14>>(buffer);
50✔
149
  auto& d4_weight = get<::Tags::Tempa<15, SpatialDim, Frame>>(buffer);
50✔
150
  auto& d4_RW_L1 = get<::Tags::Tempa<16, SpatialDim, Frame>>(buffer);
50✔
151
  auto& d4_RW_S = get<::Tags::Tempa<17, SpatialDim, Frame>>(buffer);
50✔
152
  auto& d4_RW_L2 = get<::Tags::Tempa<18, SpatialDim, Frame>>(buffer);
50✔
153
  auto& d4_mu_S = get<::Tags::Tempa<19, SpatialDim, Frame>>(buffer);
50✔
154
  auto& d4_mu1 = get<::Tags::Tempa<20, SpatialDim, Frame>>(buffer);
50✔
155
  auto& d4_mu2 = get<::Tags::Tempa<21, SpatialDim, Frame>>(buffer);
50✔
156
  auto& d4_log_fac_mu1 = get<::Tags::Tempa<22, SpatialDim, Frame>>(buffer);
50✔
157
  auto& d4_log_fac_muS = get<::Tags::Tempa<23, SpatialDim, Frame>>(buffer);
50✔
158
  auto& d4_log_fac_mu2 = get<::Tags::Tempa<24, SpatialDim, Frame>>(buffer);
50✔
159

160
  auto& spacetime_metric_dot_shift =
161
      get<::Tags::Tempa<31, SpatialDim, Frame>>(buffer);
50✔
162
  auto& prefac = get<::Tags::TempScalar<32>>(buffer);
50✔
163
  auto& d4_muS_over_lapse = get<::Tags::Tempa<33, SpatialDim, Frame>>(buffer);
50✔
164
  auto& dT1 = get<::Tags::Tempab<35, SpatialDim, Frame>>(buffer);
50✔
165
  auto& dT2 = get<::Tags::Tempa<36, SpatialDim, Frame>>(buffer);
50✔
166
  auto& dT3 = get<::Tags::Tempab<37, SpatialDim, Frame>>(buffer);
50✔
167

168
  // 3+1 quantities
169
  const tnsr::ii<DataVector, SpatialDim, Frame> spatial_metric{};
100✔
170
  for (size_t i = 0; i< SpatialDim; ++i) {
158✔
171
    for (size_t j = 0; j <= i; ++j) {
296✔
172
      make_const_view(make_not_null(&spatial_metric.get(i, j)),
188✔
173
                      spacetime_metric.get(i + 1, j + 1), 0, num_points);
174
    }
175
  }
176
  // We need \f$ \partial_a g_{bi} = \partial_a \psi_{bi} \f$. Here we
177
  // use `derivatives_of_spacetime_metric` to get \f$ \partial_a g_{bc}\f$
178
  // instead, and use only the derivatives of \f$ g_{bi}\f$.
179
  const tnsr::ii<DataVector, SpatialDim, Frame> d0_spatial_metric{};
100✔
180
  for (size_t i = 0; i < SpatialDim; ++i) {
158✔
181
    for (size_t j = i; j < SpatialDim; ++j) {
296✔
182
      make_const_view(make_not_null(&d0_spatial_metric.get(i, j)),
188✔
183
                      d4_spacetime_metric.get(0, i + 1, j + 1), 0, num_points);
184
    }
185
  }
186

187
  // commonly used terms
188
  constexpr auto exp_fac_1 = 0.5;
50✔
189
  constexpr auto exp_fac_2 = 0.;
50✔
190
  get(one_over_lapse) = 1. / get(lapse);
100✔
191
  DampedHarmonicGauge_detail::log_factor_metric_lapse<DataVector>(
50✔
192
      make_not_null(&log_fac_1), lapse, sqrt_det_spatial_metric, exp_fac_1);
193
  DampedHarmonicGauge_detail::log_factor_metric_lapse<DataVector>(
50✔
194
      make_not_null(&log_fac_2), lapse, sqrt_det_spatial_metric, exp_fac_2);
195

196
  // Tempering functions
197
  const double roll_on = UseRollon
50✔
198
                             ? DampedHarmonicGauge_detail::roll_on_function(
199
                                   time, rollon_start_time, rollon_width)
200
                             : 1.0;
201
  DampedHarmonicGauge_detail::spatial_weight_function<SpatialDim, Frame,
202
                                                      DataVector>(
50✔
203
      make_not_null(&weight), coords, sigma_r);
204

205
  // coeffs that enter gauge source function
206
  get(mu_L1) =
50✔
207
      amp_coef_L1 * roll_on * get(weight) * pow(get(log_fac_1), exp_L1);
150✔
208
  get(mu_S) = amp_coef_S * roll_on * get(weight) * pow(get(log_fac_1), exp_S);
150✔
209
  get(mu_L2) =
50✔
210
      amp_coef_L2 * roll_on * get(weight) * pow(get(log_fac_2), exp_L2);
150✔
211
  get(mu_S_over_lapse) = get(mu_S) * get(one_over_lapse);
150✔
212

213
  // Calc \f$ \mu_1 = \mu_{L1} log(rootg/N) = R W log(rootg/N)^5\f$
214
  get(mu1) = get(mu_L1) * get(log_fac_1);
150✔
215

216
  // Calc \f$ \mu_2 = \mu_{L2} log(1/N) = R W log(1/N)^5\f$
217
  get(mu2) = get(mu_L2) * get(log_fac_2);
150✔
218

219
  get(prefac) = get(mu_L1) * get(log_fac_1) + get(mu_L2) * get(log_fac_2);
250✔
220

221
  // Compute g_ai shift^i
222
  for (size_t a = 0; a < SpatialDim + 1; ++a) {
208✔
223
    spacetime_metric_dot_shift.get(a) =
158✔
224
        spacetime_metric.get(a, 1) * shift.get(0);
158✔
225
    for (size_t i = 1; i < SpatialDim; ++i) {
376✔
226
      spacetime_metric_dot_shift.get(a) +=
218✔
227
          spacetime_metric.get(a, i + 1) * shift.get(i);
436✔
228
    }
229
  }
230

231
  // Calculate H_a
232
  for (size_t a = 0; a < SpatialDim + 1; ++a) {
208✔
233
    gauge_h->get(a) = -get(mu_S_over_lapse) * spacetime_metric_dot_shift.get(a);
316✔
234
    if constexpr (UseRollon) {
235
      gauge_h->get(a) += (1. - roll_on) * gauge_h_init->get(a);
9✔
236
    }
237
  }
238
  // Since n_i = 0 only do H_0 term
239
  gauge_h->get(0) += get(prefac) * spacetime_unit_normal_one_form.get(0);
100✔
240

241
  [[maybe_unused]] const double d0_roll_on =
50✔
242
      UseRollon ? DampedHarmonicGauge_detail::time_deriv_of_roll_on_function(
243
                      time, rollon_start_time, rollon_width)
244
                : 0.0;
245

246
  // Calc \f$ \partial_a [R W] \f$
247
  DampedHarmonicGauge_detail::spacetime_deriv_of_spatial_weight_function<
248
      SpatialDim, Frame, DataVector>(make_not_null(&d4_weight), coords, sigma_r,
50✔
249
                                     weight);
250
  d4_RW_L1 = d4_weight;
50✔
251
  d4_RW_S = d4_weight;
50✔
252
  d4_RW_L2 = d4_weight;
50✔
253
  if constexpr (UseRollon) {
254
    for (size_t a = 0; a < SpatialDim + 1; ++a) {
12✔
255
      d4_RW_L1.get(a) *= roll_on;
9✔
256
      d4_RW_S.get(a) *= roll_on;
9✔
257
      d4_RW_L2.get(a) *= roll_on;
9✔
258
    }
259
    get<0>(d4_RW_L1) += get(weight) * d0_roll_on;
6✔
260
    get<0>(d4_RW_S) += get(weight) * d0_roll_on;
6✔
261
    get<0>(d4_RW_L2) += get(weight) * d0_roll_on;
6✔
262
  }
263

264
  // \partial_a \mu_{S} = \partial_a(A_S R_S W
265
  //                               \log(\sqrt{g}/N)^{c_{S}})
266
  // \partial_a \mu_1 = \partial_a(A_L1 R_L1 W
267
  //                               \log(\sqrt{g}/N)^{1+c_{L1}})
268
  // \partial_a \mu_2 = \partial_a(A_L2 R_L2 W
269
  //                               \log(1/N)^{1+c_{L2}})
270
  DampedHarmonicGauge_detail::spacetime_deriv_of_power_log_factor_metric_lapse<
271
      SpatialDim, Frame, DataVector>(
50✔
272
      make_not_null(&d4_log_fac_mu1), lapse, shift, spacetime_unit_normal,
273
      inverse_spatial_metric, sqrt_det_spatial_metric, d0_spatial_metric, pi,
274
      phi, exp_fac_1, exp_L1 + 1);
275
  DampedHarmonicGauge_detail::spacetime_deriv_of_power_log_factor_metric_lapse<
276
      SpatialDim, Frame, DataVector>(
50✔
277
      make_not_null(&d4_log_fac_muS), lapse, shift, spacetime_unit_normal,
278
      inverse_spatial_metric, sqrt_det_spatial_metric, d0_spatial_metric, pi,
279
      phi, exp_fac_1, exp_S);
280
  DampedHarmonicGauge_detail::spacetime_deriv_of_power_log_factor_metric_lapse<
281
      SpatialDim, Frame, DataVector>(
50✔
282
      make_not_null(&d4_log_fac_mu2), lapse, shift, spacetime_unit_normal,
283
      inverse_spatial_metric, sqrt_det_spatial_metric, d0_spatial_metric, pi,
284
      phi, exp_fac_2, exp_L2 + 1);
285
  for (size_t a = 0; a < SpatialDim + 1; ++a) {
208✔
286
    // \f$ \partial_a \mu_1 \f$
287
    d4_mu1.get(a) =
158✔
288
        amp_coef_L1 * pow(get(log_fac_1), exp_L1 + 1) * d4_RW_L1.get(a) +
316✔
289
        amp_coef_L1 * roll_on * get(weight) * d4_log_fac_mu1.get(a);
316✔
290
    // \f$ \partial_a \mu_{S} \f$
291
    d4_mu_S.get(a) = amp_coef_S * d4_RW_S.get(a) * pow(get(log_fac_1), exp_S) +
158✔
292
                     amp_coef_S * roll_on * get(weight) * d4_log_fac_muS.get(a);
316✔
293
    // \f$ \partial_a \mu_2 \f$
294
    d4_mu2.get(a) =
158✔
295
        amp_coef_L2 * pow(get(log_fac_2), exp_L2 + 1) * d4_RW_L2.get(a) +
316✔
296
        amp_coef_L2 * roll_on * get(weight) * d4_log_fac_mu2.get(a);
474✔
297
  }
298

299
  const tnsr::ijj<DataVector, SpatialDim, Frame> d3_spatial_metric{};
100✔
300
  for (size_t i = 0; i < SpatialDim; ++i) {
158✔
301
    for (size_t j = 0; j < SpatialDim; ++j) {
376✔
302
      for (size_t k = 0; k <= j; ++k) {
762✔
303
        make_const_view(make_not_null(&d3_spatial_metric.get(i, j, k)),
494✔
304
                        phi.get(i, j + 1, k + 1), 0, num_points);
305
      }
306
    }
307
  }
308

309
  // Calc \f$ \partial_a T1 \f$
310
  if constexpr (UseRollon) {
311
    for (size_t b = 0; b < SpatialDim + 1; ++b) {
12✔
312
      dT1.get(0, b) = -gauge_h_init->get(b) * d0_roll_on;
9✔
313
      for (size_t a = 0; a < SpatialDim + 1; ++a) {
38✔
314
        if (a != 0) {
29✔
315
          dT1.get(a, b) = (1. - roll_on) * dgauge_h_init->get(a, b);
20✔
316
        } else {
317
          dT1.get(a, b) += (1. - roll_on) * dgauge_h_init->get(a, b);
9✔
318
        }
319
      }
320
    }
321
  }
322

323
  // d_t lapse / lapse = 0.5 * n^a n^b (lapse Pi_{ab} - shift^i Phi_{iab})
324
  get<0>(d4_muS_over_lapse) = -get<0>(shift) * get<0>(half_phi_two_normals);
150✔
325
  for (size_t i = 1; i < SpatialDim; ++i) {
108✔
326
    get<0>(d4_muS_over_lapse) -= shift.get(i) * half_phi_two_normals.get(i);
116✔
327
  }
328
  get<0>(d4_muS_over_lapse) += get(lapse) * get(half_pi_two_normals);
150✔
329
  get<0>(d4_muS_over_lapse) *= get(lapse);
100✔
330

331
  // Calc \f$ \partial_a T2 \f$
332
  get<0>(dT2) =
50✔
333
      (get<0>(d4_mu1) + get<0>(d4_mu2)) * get<0>(spacetime_unit_normal_one_form)
150✔
334
      // Note:  \f$ \partial_a n_b = {-\partial_a lapse, 0, 0, 0} \f$
335
      - (get(mu1) + get(mu2)) * get<0>(d4_muS_over_lapse);
200✔
336

337
  for (size_t i = 0; i < SpatialDim; ++i) {
158✔
338
    dT2.get(i + 1) =
108✔
339
        (d4_mu1.get(i + 1) + d4_mu2.get(i + 1)) *
108✔
340
            get<0>(spacetime_unit_normal_one_form)
108✔
341
        // Note:  \f$ \partial_a n_b = {-\partial_a lapse, 0, 0, 0} \f$
342
        + (get(mu1) + get(mu2)) * get(lapse) * half_phi_two_normals.get(i);
648✔
343
  }
344

345
  // \f[ \partial_a (\mu_S/N) = (1/N) \partial_a \mu_{S}
346
  //         - (\mu_{S}/N^2) \partial_a N
347
  // \f]
348
  //
349
  // Note that the d4_lapse terms are actually
350
  // d_t lapse / lapse = 0.5 * n^a n^b (lapse Pi_{ab} - shift^i Phi_{iab})
351
  // d_i lapse / lapse = -0.5 * n^a n^b Phi_{iab}
352
  //
353
  // The GH RHS computes:
354
  //  0.5 * n^a n^b Pi_{ab}
355
  //  0.5 * n^a n^b Phi_{iab}
356
  // so we reuse that work by taking them as arguments.
357
  get<0>(d4_muS_over_lapse) *= -get(mu_S);
100✔
358
  get<0>(d4_muS_over_lapse) += get<0>(d4_mu_S);
100✔
359
  get<0>(d4_muS_over_lapse) *= get(one_over_lapse);
100✔
360
  for (size_t i = 0; i < SpatialDim; ++i) {
158✔
361
    d4_muS_over_lapse.get(i + 1) =
108✔
362
        get(one_over_lapse) *
108✔
363
        (d4_mu_S.get(i + 1) + get(mu_S) * half_phi_two_normals.get(i));
324✔
364
  }
365

366
  // Calc \f$ \partial_a T3 \f$ (note minus sign)
367
  for (size_t a = 0; a < SpatialDim + 1; ++a) {
208✔
368
    for (size_t j = 0; j < SpatialDim; ++j) {
534✔
369
      dT3.get(a, j + 1) = d4_spacetime_metric.get(a, 0, j + 1);
376✔
370
    }
371
    dT3.get(a, 0) = d4_spacetime_metric.get(a, 0, 1) * get<0>(shift);
158✔
372
    for (size_t j = 1; j < SpatialDim; ++j) {
376✔
373
      dT3.get(a, 0) += d4_spacetime_metric.get(a, 0, j + 1) * shift.get(j);
218✔
374
    }
375
    for (size_t i = 0; i < SpatialDim; ++i) {
534✔
376
      for (size_t j = i + 1; j < SpatialDim; ++j) {
682✔
377
        dT3.get(a, 0) -= shift.get(i) * shift.get(j) *
306✔
378
                         d4_spacetime_metric.get(a, i + 1, j + 1);
379
      }
380
    }
381
    dT3.get(a, 0) *= 2.0;
158✔
382
    for (size_t i = 0; i < SpatialDim; ++i) {
534✔
383
      dT3.get(a, 0) -= shift.get(i) * shift.get(i) *
376✔
384
                       d4_spacetime_metric.get(a, i + 1, i + 1);
385
    }
386

387
    for (size_t b = 0; b < SpatialDim + 1; ++b) {
692✔
388
      dT3.get(a, b) *= -get(mu_S_over_lapse);
534✔
389
      dT3.get(a, b) -=
534✔
390
          d4_muS_over_lapse.get(a) * spacetime_metric_dot_shift.get(b);
1,068✔
391
    }
392
  }
393

394
  // Calc \f$ \partial_a H_b = dT1_{ab} + dT2_{ab} + dT3_{ab} \f$
395
  for (size_t a = 0; a < SpatialDim + 1; ++a) {
208✔
396
    for (size_t b = 0; b < SpatialDim + 1; ++b) {
692✔
397
      if constexpr (UseRollon) {
398
        d4_gauge_h->get(a, b) = dT1.get(a, b) +  dT3.get(a, b);
29✔
399
      } else {
400
        d4_gauge_h->get(a, b) = dT3.get(a, b);
505✔
401
      }
402
    }
403
    d4_gauge_h->get(a, 0) += dT2.get(a);
158✔
404
  }
405
}
50✔
406
}  // namespace
407

408
template <size_t SpatialDim, typename Frame>
409
void damped_harmonic_rollon(
3✔
410
    const gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame>*> gauge_h,
411
    const gsl::not_null<tnsr::ab<DataVector, SpatialDim, Frame>*> d4_gauge_h,
412
    const tnsr::a<DataVector, SpatialDim, Frame>& gauge_h_init,
413
    const tnsr::ab<DataVector, SpatialDim, Frame>& dgauge_h_init,
414
    const Scalar<DataVector>& lapse,
415
    const tnsr::I<DataVector, SpatialDim, Frame>& shift,
416
    const tnsr::a<DataVector, SpatialDim, Frame>&
417
        spacetime_unit_normal_one_form,
418
    const tnsr::A<DataVector, SpatialDim, Frame>& spacetime_unit_normal,
419
    const Scalar<DataVector>& sqrt_det_spatial_metric,
420
    const tnsr::II<DataVector, SpatialDim, Frame>& inverse_spatial_metric,
421
    const tnsr::abb<DataVector, SpatialDim, Frame>& d4_spacetime_metric,
422
    const Scalar<DataVector>& half_pi_two_normals,
423
    const tnsr::i<DataVector, SpatialDim, Frame>& half_phi_two_normals,
424
    const tnsr::aa<DataVector, SpatialDim, Frame>& spacetime_metric,
425
    const tnsr::aa<DataVector, SpatialDim, Frame>& pi,
426
    const tnsr::iaa<DataVector, SpatialDim, Frame>& phi, const double time,
427
    const tnsr::I<DataVector, SpatialDim, Frame>& coords,
428
    const double amp_coef_L1, const double amp_coef_L2, const double amp_coef_S,
429
    const int exp_L1, const int exp_L2, const int exp_S,
430
    const double rollon_start_time, const double rollon_width,
431
    const double sigma_r) {
432
  damped_harmonic_impl<true>(
3✔
433
      gauge_h, d4_gauge_h, &gauge_h_init, &dgauge_h_init, lapse, shift,
434
      spacetime_unit_normal_one_form, spacetime_unit_normal,
435
      sqrt_det_spatial_metric, inverse_spatial_metric, d4_spacetime_metric,
436
      half_pi_two_normals, half_phi_two_normals, spacetime_metric, pi, phi,
437
      time, coords, amp_coef_L1, amp_coef_L2, amp_coef_S, exp_L1, exp_L2, exp_S,
438
      rollon_start_time, rollon_width, sigma_r);
439
}
3✔
440

441
template <size_t SpatialDim, typename Frame>
442
void damped_harmonic(
47✔
443
    const gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame>*> gauge_h,
444
    const gsl::not_null<tnsr::ab<DataVector, SpatialDim, Frame>*> d4_gauge_h,
445
    const Scalar<DataVector>& lapse,
446
    const tnsr::I<DataVector, SpatialDim, Frame>& shift,
447
    const tnsr::a<DataVector, SpatialDim, Frame>&
448
        spacetime_unit_normal_one_form,
449
    const tnsr::A<DataVector, SpatialDim, Frame>& spacetime_unit_normal,
450
    const Scalar<DataVector>& sqrt_det_spatial_metric,
451
    const tnsr::II<DataVector, SpatialDim, Frame>& inverse_spatial_metric,
452
    const tnsr::abb<DataVector, SpatialDim, Frame>& d4_spacetime_metric,
453
    const Scalar<DataVector>& half_pi_two_normals,
454
    const tnsr::i<DataVector, SpatialDim, Frame>& half_phi_two_normals,
455
    const tnsr::aa<DataVector, SpatialDim, Frame>& spacetime_metric,
456
    const tnsr::aa<DataVector, SpatialDim, Frame>& pi,
457
    const tnsr::iaa<DataVector, SpatialDim, Frame>& phi,
458
    const tnsr::I<DataVector, SpatialDim, Frame>& coords,
459
    const double amp_coef_L1, const double amp_coef_L2, const double amp_coef_S,
460
    const int exp_L1, const int exp_L2, const int exp_S, const double sigma_r) {
461
  damped_harmonic_impl<false, SpatialDim, Frame>(
47✔
462
      gauge_h, d4_gauge_h, nullptr, nullptr, lapse, shift,
463
      spacetime_unit_normal_one_form, spacetime_unit_normal,
464
      sqrt_det_spatial_metric, inverse_spatial_metric, d4_spacetime_metric,
465
      half_pi_two_normals, half_phi_two_normals, spacetime_metric, pi, phi,
466
      std::numeric_limits<double>::signaling_NaN(), coords, amp_coef_L1,
467
      amp_coef_L2, amp_coef_S, exp_L1, exp_L2, exp_S,
468
      std::numeric_limits<double>::signaling_NaN(),
469
      std::numeric_limits<double>::signaling_NaN(), sigma_r);
470
}
47✔
471

472
DampedHarmonic::DampedHarmonic(const double width,
14✔
473
                               const std::array<double, 3>& amps,
474
                               const std::array<int, 3>& exps)
14✔
475
    : spatial_decay_width_(width), amplitudes_(amps), exponents_(exps) {}
14✔
476

477
DampedHarmonic::DampedHarmonic(CkMigrateMessage* const msg)
6✔
478
    : GaugeCondition(msg) {}
6✔
479

480
void DampedHarmonic::pup(PUP::er& p) {
18✔
481
  GaugeCondition::pup(p);
18✔
482
  p | spatial_decay_width_;
18✔
483
  p | amplitudes_;
18✔
484
  p | exponents_;
18✔
485
}
18✔
486

487
std::unique_ptr<GaugeCondition> DampedHarmonic::get_clone() const {
6✔
488
  return std::make_unique<DampedHarmonic>(*this);
6✔
489
}
490

491
template <size_t SpatialDim>
492
void DampedHarmonic::gauge_and_spacetime_derivative(
38✔
493
    const gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame::Inertial>*>
494
        gauge_h,
495
    const gsl::not_null<tnsr::ab<DataVector, SpatialDim, Frame::Inertial>*>
496
        d4_gauge_h,
497
    const Scalar<DataVector>& lapse,
498
    const tnsr::I<DataVector, SpatialDim, Frame::Inertial>& shift,
499
    const tnsr::a<DataVector, SpatialDim, Frame::Inertial>&
500
        spacetime_unit_normal_one_form,
501
    const tnsr::A<DataVector, SpatialDim, Frame::Inertial>&
502
        spacetime_unit_normal,
503
    const Scalar<DataVector>& sqrt_det_spatial_metric,
504
    const tnsr::II<DataVector, SpatialDim, Frame::Inertial>&
505
        inverse_spatial_metric,
506
    const tnsr::abb<DataVector, SpatialDim, Frame::Inertial>&
507
        d4_spacetime_metric,
508
    const Scalar<DataVector>& half_pi_two_normals,
509
    const tnsr::i<DataVector, SpatialDim, Frame::Inertial>&
510
        half_phi_two_normals,
511
    const tnsr::aa<DataVector, SpatialDim, Frame::Inertial>& spacetime_metric,
512
    const tnsr::aa<DataVector, SpatialDim, Frame::Inertial>& pi,
513
    const tnsr::iaa<DataVector, SpatialDim, Frame::Inertial>& phi,
514
    const double /*time*/,
515
    const tnsr::I<DataVector, SpatialDim, Frame::Inertial>& inertial_coords)
516
    const {
517
  damped_harmonic(
38✔
518
      gauge_h, d4_gauge_h, lapse, shift, spacetime_unit_normal_one_form,
519
      spacetime_unit_normal, sqrt_det_spatial_metric, inverse_spatial_metric,
520
      d4_spacetime_metric, half_pi_two_normals, half_phi_two_normals,
521
      spacetime_metric, pi, phi, inertial_coords, amplitudes_[0],
522
      amplitudes_[1], amplitudes_[2], exponents_[0], exponents_[1],
523
      exponents_[2], spatial_decay_width_);
38✔
524
}
38✔
525

526
// NOLINTNEXTLINE
527
PUP::able::PUP_ID DampedHarmonic::my_PUP_ID = 0;
528

529
#define DIM(data) BOOST_PP_TUPLE_ELEM(0, data)
530

531
#define INSTANTIATE(_, data)                                                   \
532
  template void DampedHarmonic::gauge_and_spacetime_derivative(                \
533
      gsl::not_null<tnsr::a<DataVector, DIM(data), Frame::Inertial>*> gauge_h, \
534
      gsl::not_null<tnsr::ab<DataVector, DIM(data), Frame::Inertial>*>         \
535
          d4_gauge_h,                                                          \
536
      const Scalar<DataVector>& lapse,                                         \
537
      const tnsr::I<DataVector, DIM(data), Frame::Inertial>& shift,            \
538
      const tnsr::a<DataVector, DIM(data), Frame::Inertial>&                   \
539
          spacetime_unit_normal_one_form,                                      \
540
      const tnsr::A<DataVector, DIM(data), Frame::Inertial>&                   \
541
          spacetime_unit_normal,                                               \
542
      const Scalar<DataVector>& sqrt_det_spatial_metric,                       \
543
      const tnsr::II<DataVector, DIM(data), Frame::Inertial>&                  \
544
          inverse_spatial_metric,                                              \
545
      const tnsr::abb<DataVector, DIM(data), Frame::Inertial>&                 \
546
          d4_spacetime_metric,                                                 \
547
      const Scalar<DataVector>& half_pi_two_normals,                           \
548
      const tnsr::i<DataVector, DIM(data), Frame::Inertial>&                   \
549
          half_phi_two_normals,                                                \
550
      const tnsr::aa<DataVector, DIM(data), Frame::Inertial>&                  \
551
          spacetime_metric,                                                    \
552
      const tnsr::aa<DataVector, DIM(data), Frame::Inertial>& pi,              \
553
      const tnsr::iaa<DataVector, DIM(data), Frame::Inertial>& phi,            \
554
      const double /*time*/,                                                   \
555
      const tnsr::I<DataVector, DIM(data), Frame::Inertial>& inertial_coords)  \
556
      const;
557

558
GENERATE_INSTANTIATIONS(INSTANTIATE, (1, 2, 3))
559

560
#undef INSTANTIATE
561

562
#define DTYPE(data) BOOST_PP_TUPLE_ELEM(1, data)
563
#define FRAME(data) BOOST_PP_TUPLE_ELEM(2, data)
564
#define DTYPE_SCAL(data) BOOST_PP_TUPLE_ELEM(0, data)
565

566
#define INSTANTIATE_DV_FUNC(_, data)                                           \
567
  template void damped_harmonic_rollon(                                        \
568
      gsl::not_null<tnsr::a<DataVector, DIM(data), FRAME(data)>*> gauge_h,     \
569
      gsl::not_null<tnsr::ab<DataVector, DIM(data), FRAME(data)>*> d4_gauge_h, \
570
      const tnsr::a<DataVector, DIM(data), FRAME(data)>& gauge_h_init,         \
571
      const tnsr::ab<DataVector, DIM(data), FRAME(data)>& dgauge_h_init,       \
572
      const Scalar<DataVector>& lapse,                                         \
573
      const tnsr::I<DataVector, DIM(data), FRAME(data)>& shift,                \
574
      const tnsr::a<DataVector, DIM(data), FRAME(data)>&                       \
575
          spacetime_unit_normal_one_form,                                      \
576
      const tnsr::A<DataVector, DIM(data), FRAME(data)>&                       \
577
          spacetime_unit_normal,                                               \
578
      const Scalar<DataVector>& sqrt_det_spatial_metric,                       \
579
      const tnsr::II<DataVector, DIM(data), FRAME(data)>&                      \
580
          inverse_spatial_metric,                                              \
581
      const tnsr::abb<DataVector, DIM(data), FRAME(data)>&                     \
582
          d4_spacetime_metric,                                                 \
583
      const Scalar<DataVector>& half_pi_two_normals,                           \
584
      const tnsr::i<DataVector, DIM(data), FRAME(data)>& half_phi_two_normals, \
585
      const tnsr::aa<DataVector, DIM(data), FRAME(data)>& spacetime_metric,    \
586
      const tnsr::aa<DataVector, DIM(data), FRAME(data)>& pi,                  \
587
      const tnsr::iaa<DataVector, DIM(data), FRAME(data)>& phi,                \
588
      const double time,                                                       \
589
      const tnsr::I<DataVector, DIM(data), FRAME(data)>& coords,               \
590
      const double amp_coef_L1, const double amp_coef_L2,                      \
591
      const double amp_coef_S, const int exp_L1, const int exp_L2,             \
592
      const int exp_S, const double rollon_start_time,                         \
593
      const double rollon_width, const double sigma_r);                        \
594
  template void damped_harmonic(                                               \
595
      gsl::not_null<tnsr::a<DataVector, DIM(data), FRAME(data)>*> gauge_h,     \
596
      gsl::not_null<tnsr::ab<DataVector, DIM(data), FRAME(data)>*> d4_gauge_h, \
597
      const Scalar<DataVector>& lapse,                                         \
598
      const tnsr::I<DataVector, DIM(data), FRAME(data)>& shift,                \
599
      const tnsr::a<DataVector, DIM(data), FRAME(data)>&                       \
600
          spacetime_unit_normal_one_form,                                      \
601
      const tnsr::A<DataVector, DIM(data), FRAME(data)>&                       \
602
          spacetime_unit_normal,                                               \
603
      const Scalar<DataVector>& sqrt_det_spatial_metric,                       \
604
      const tnsr::II<DataVector, DIM(data), FRAME(data)>&                      \
605
          inverse_spatial_metric,                                              \
606
      const tnsr::abb<DataVector, DIM(data), FRAME(data)>&                     \
607
          d4_spacetime_metric,                                                 \
608
      const Scalar<DataVector>& half_pi_two_normals,                           \
609
      const tnsr::i<DataVector, DIM(data), FRAME(data)>& half_phi_two_normals, \
610
      const tnsr::aa<DataVector, DIM(data), FRAME(data)>& spacetime_metric,    \
611
      const tnsr::aa<DataVector, DIM(data), FRAME(data)>& pi,                  \
612
      const tnsr::iaa<DataVector, DIM(data), FRAME(data)>& phi,                \
613
      const tnsr::I<DataVector, DIM(data), FRAME(data)>& coords,               \
614
      const double amp_coef_L1, const double amp_coef_L2,                      \
615
      const double amp_coef_S, const int exp_L1, const int exp_L2,             \
616
      const int exp_S, const double sigma_r);
617

618
GENERATE_INSTANTIATIONS(INSTANTIATE_DV_FUNC, (1, 2, 3), (DataVector),
619
                        (Frame::Inertial))
620

621
#undef DIM
622
#undef DTYPE
623
#undef FRAME
624
#undef DTYPE_SCAL
625
#undef INSTANTIATE_DV_FUNC
626
#undef INSTANTIATE_SCALAR_FUNC
627
}  // namespace GeneralizedHarmonic::gauges
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc