Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : ///\file
5 : /// Defines functions to calculate the generalized harmonic constraints
6 :
7 : #pragma once
8 :
9 : #include <cstddef>
10 :
11 : #include "DataStructures/DataBox/Prefixes.hpp"
12 : #include "DataStructures/DataBox/Tag.hpp"
13 : #include "DataStructures/DataVector.hpp"
14 : #include "DataStructures/Tensor/TypeAliases.hpp"
15 : #include "Evolution/Systems/GeneralizedHarmonic/Tags.hpp"
16 : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp"
17 : #include "PointwiseFunctions/GeneralRelativity/GeneralizedHarmonic/ConstraintDampingTags.hpp"
18 : #include "Utilities/SetNumberOfGridPoints.hpp"
19 : #include "Utilities/TMPL.hpp"
20 :
21 : /// \cond
22 : namespace gsl {
23 : template <typename T>
24 : class not_null;
25 : } // namespace gsl
26 : /// \endcond
27 :
28 : namespace gh {
29 : /// @{
30 : /*!
31 : * \brief Computes the generalized-harmonic 3-index constraint.
32 : *
33 : * \details Computes the generalized-harmonic 3-index constraint,
34 : * \f$C_{iab} = \partial_i g_{ab} - \Phi_{iab},\f$ which is
35 : * given by Eq. (26) of \cite Lindblom2005qh
36 : */
37 : template <typename DataType, size_t SpatialDim, typename Frame>
38 1 : tnsr::iaa<DataType, SpatialDim, Frame> three_index_constraint(
39 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_spacetime_metric,
40 : const tnsr::iaa<DataType, SpatialDim, Frame>& phi);
41 :
42 : template <typename DataType, size_t SpatialDim, typename Frame>
43 1 : void three_index_constraint(
44 : gsl::not_null<tnsr::iaa<DataType, SpatialDim, Frame>*> constraint,
45 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_spacetime_metric,
46 : const tnsr::iaa<DataType, SpatialDim, Frame>& phi);
47 : /// @}
48 :
49 : /// @{
50 : /*!
51 : * \brief Computes the generalized-harmonic gauge constraint.
52 : *
53 : * \details Computes the generalized-harmonic gauge constraint
54 : * [Eq. (40) of \cite Lindblom2005qh],
55 : * \f[
56 : * C_a = H_a + \gamma^{ij} \Phi_{ija} + n^b \Pi_{ba}
57 : * - \frac{1}{2} \gamma^i_a g^{bc} \Phi_{ibc}
58 : * - \frac{1}{2} n_a g^{bc} \Pi_{bc},
59 : * \f]
60 : * where \f$H_a\f$ is the gauge function,
61 : * \f$g_{ab}\f$ is the spacetime metric,
62 : * \f$\Pi_{ab}=-n^c\partial_c g_{ab}\f$, and
63 : * \f$\Phi_{iab} = \partial_i g_{ab}\f$; \f$n^a\f$ is the timelike unit
64 : * normal vector to the spatial slice, \f$\gamma^{ij}\f$ is the inverse spatial
65 : * metric, and \f$\gamma^b_c = \delta^b_c + n^b n_c\f$.
66 : */
67 : template <typename DataType, size_t SpatialDim, typename Frame>
68 1 : tnsr::a<DataType, SpatialDim, Frame> gauge_constraint(
69 : const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
70 : const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
71 : const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
72 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
73 : const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
74 : const tnsr::aa<DataType, SpatialDim, Frame>& pi,
75 : const tnsr::iaa<DataType, SpatialDim, Frame>& phi);
76 :
77 : template <typename DataType, size_t SpatialDim, typename Frame>
78 1 : void gauge_constraint(
79 : gsl::not_null<tnsr::a<DataType, SpatialDim, Frame>*> constraint,
80 : const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
81 : const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
82 : const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
83 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
84 : const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
85 : const tnsr::aa<DataType, SpatialDim, Frame>& pi,
86 : const tnsr::iaa<DataType, SpatialDim, Frame>& phi);
87 : /// @}
88 :
89 : /// @{
90 : /*!
91 : * \brief Computes the generalized-harmonic 2-index constraint.
92 : *
93 : * \details Computes the generalized-harmonic 2-index constraint
94 : * [Eq. (44) of \cite Lindblom2005qh],
95 : * \f{eqnarray}{
96 : * C_{ia} &\equiv& \gamma^{jk}\partial_j \Phi_{ika}
97 : * - \frac{1}{2} \gamma_a^j g^{cd}\partial_j \Phi_{icd}
98 : * + n^b \partial_i \Pi_{ba}
99 : * - \frac{1}{2} n_a g^{cd}\partial_i\Pi_{cd}
100 : * \nonumber\\&&
101 : * + \partial_i H_a
102 : * + \frac{1}{2} \gamma_a^j \Phi_{jcd} \Phi_{ief}
103 : * g^{ce}g^{df}
104 : * + \frac{1}{2} \gamma^{jk} \Phi_{jcd} \Phi_{ike}
105 : * g^{cd}n^e n_a
106 : * \nonumber\\&&
107 : * - \gamma^{jk}\gamma^{mn}\Phi_{jma}\Phi_{ikn}
108 : * + \frac{1}{2} \Phi_{icd} \Pi_{be} n_a
109 : * \left(g^{cb}g^{de}
110 : * +\frac{1}{2}g^{be} n^c n^d\right)
111 : * \nonumber\\&&
112 : * - \Phi_{icd} \Pi_{ba} n^c \left(g^{bd}
113 : * +\frac{1}{2} n^b n^d\right)
114 : * + \frac{1}{2} \gamma_2 \left(n_a g^{cd}
115 : * - 2 \delta^c_a n^d\right) C_{icd}.
116 : * \f}
117 : * where \f$H_a\f$ is the gauge function,
118 : * \f$g_{ab}\f$ is the spacetime metric,
119 : * \f$\Pi_{ab}=-n^c\partial_c g_{ab}\f$, and
120 : * \f$\Phi_{iab} = \partial_i g_{ab}\f$; \f$n^a\f$ is the timelike unit
121 : * normal vector to the spatial slice, \f$\gamma^{ij}\f$ is the inverse spatial
122 : * metric, and \f$\gamma^b_c = \delta^b_c + n^b n_c\f$.
123 : */
124 : template <typename DataType, size_t SpatialDim, typename Frame>
125 1 : tnsr::ia<DataType, SpatialDim, Frame> two_index_constraint(
126 : const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
127 : const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
128 : const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
129 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
130 : const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
131 : const tnsr::aa<DataType, SpatialDim, Frame>& pi,
132 : const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
133 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
134 : const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
135 : const Scalar<DataType>& gamma2,
136 : const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint);
137 :
138 : template <typename DataType, size_t SpatialDim, typename Frame>
139 1 : void two_index_constraint(
140 : gsl::not_null<tnsr::ia<DataType, SpatialDim, Frame>*> constraint,
141 : const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
142 : const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
143 : const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
144 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
145 : const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
146 : const tnsr::aa<DataType, SpatialDim, Frame>& pi,
147 : const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
148 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
149 : const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
150 : const Scalar<DataType>& gamma2,
151 : const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint);
152 : /// @}
153 :
154 : /// @{
155 : /*!
156 : * \brief Computes the generalized-harmonic 4-index constraint.
157 : *
158 : * \details Computes the independent components of the generalized-harmonic
159 : * 4-index constraint. The constraint itself is given by Eq. (45) of
160 : * \cite Lindblom2005qh,
161 : * \f{eqnarray}{
162 : * C_{ijab} = 2 \partial_{[i}\Phi_{j]ab},
163 : * \f}
164 : * where \f$\Phi_{iab} = \partial_i g_{ab}\f$. Because the constraint is
165 : * antisymmetric on the two spatial indices, here we compute and store
166 : * only the independent components of \f$C_{ijab}\f$. Specifically, we
167 : * compute
168 : * \f{eqnarray}{
169 : * D_{iab} \equiv \frac{1}{2} \epsilon_{i}{}^{jk} C_{jkab}
170 : * = \epsilon_{i}{}^{jk} \partial_j \Phi_{kab},
171 : * \f}
172 : * where \f$\epsilon_{ijk}\f$ is the flat-space Levi-Civita symbol,
173 : * which is raised and lowered with the Kronecker delta.
174 : * In terms
175 : * of \f$D_{iab}\f$, the full 4-index constraint is
176 : * \f{eqnarray}{
177 : * C_{jkab} = \epsilon^{i}{}_{jk} D_{iab}.
178 : * \f}
179 : */
180 : template <typename DataType, size_t SpatialDim, typename Frame>
181 1 : tnsr::iaa<DataType, SpatialDim, Frame> four_index_constraint(
182 : const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi);
183 :
184 : template <typename DataType, size_t SpatialDim, typename Frame>
185 1 : void four_index_constraint(
186 : gsl::not_null<tnsr::iaa<DataType, SpatialDim, Frame>*> constraint,
187 : const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi);
188 : /// @}
189 :
190 : /// @{
191 : /*!
192 : * \brief Computes the generalized-harmonic F constraint.
193 : *
194 : * \details Computes the generalized-harmonic F constraint
195 : * [Eq. (43) of \cite Lindblom2005qh],
196 : * \f{eqnarray}{
197 : * {\cal F}_a &\equiv&
198 : * \frac{1}{2} \gamma_a^i g^{bc}\partial_i \Pi_{bc}
199 : * - \gamma^{ij} \partial_i \Pi_{ja}
200 : * - \gamma^{ij} n^b \partial_i \Phi_{jba}
201 : * + \frac{1}{2} n_a g^{bc} \gamma^{ij} \partial_i \Phi_{jbc}
202 : * \nonumber \\ &&
203 : * + n_a \gamma^{ij} \partial_i H_j
204 : * + \gamma_a^i \Phi_{ijb} \gamma^{jk}\Phi_{kcd} g^{bd} n^c
205 : * - \frac{1}{2} \gamma_a^i \Phi_{ijb} \gamma^{jk}
206 : * \Phi_{kcd} g^{cd} n^b
207 : * \nonumber \\ &&
208 : * - \gamma_a^i n^b \partial_i H_b
209 : * + \gamma^{ij} \Phi_{icd} \Phi_{jba} g^{bc} n^d
210 : * - \frac{1}{2} n_a \gamma^{ij} \gamma^{mn} \Phi_{imc} \Phi_{njd}g^{cd}
211 : * \nonumber \\ &&
212 : * - \frac{1}{4} n_a \gamma^{ij}\Phi_{icd}\Phi_{jbe}
213 : * g^{cb}g^{de}
214 : * + \frac{1}{4} n_a \Pi_{cd} \Pi_{be}
215 : * g^{cb}g^{de}
216 : * - \gamma^{ij} H_i \Pi_{ja}
217 : * \nonumber \\ &&
218 : * - n^b \gamma^{ij} \Pi_{b i} \Pi_{ja}
219 : * - \frac{1}{4} \gamma_a^i \Phi_{icd} n^c n^d \Pi_{be}
220 : * g^{be}
221 : * + \frac{1}{2} n_a \Pi_{cd} \Pi_{be}g^{ce}
222 : * n^d n^b
223 : * \nonumber \\ &&
224 : * + \gamma_a^i \Phi_{icd} \Pi_{be} n^c n^b g^{de}
225 : * - \gamma^{ij}\Phi_{iba} n^b \Pi_{je} n^e
226 : * - \frac{1}{2} \gamma^{ij}\Phi_{icd} n^c n^d \Pi_{ja}
227 : * \nonumber \\ &&
228 : * - \gamma^{ij} H_i \Phi_{jba} n^b
229 : * + \gamma_{a}^i \Phi_{icd} H_b g^{bc} n^d
230 : * +\gamma_2\bigl(\gamma^{id}{\cal C}_{ida}
231 : * -\frac{1}{2} \gamma_a^i g^{cd}{\cal C}_{icd}\bigr)
232 : * \nonumber \\ &&
233 : * + \frac{1}{2} n_a \Pi_{cd}g^{cd} H_b n^b
234 : * - n_a \gamma^{ij} \Phi_{ijc} H_d g^{cd}
235 : * +\frac{1}{2} n_a \gamma^{ij} H_i \Phi_{jcd}g^{cd}
236 : * \nonumber \\ &&
237 : * - 16 \pi n^a T_{a b}
238 : * \f}
239 : * where \f$H_a\f$ is the gauge function,
240 : * \f$g_{ab}\f$ is the spacetime metric,
241 : * \f$\Pi_{ab}=-n^c\partial_c g_{ab}\f$, and
242 : * \f$\Phi_{iab} = \partial_i g_{ab}\f$; \f$n^a\f$ is the timelike unit
243 : * normal vector to the spatial slice, \f$\gamma^{ij}\f$ is the inverse spatial
244 : * metric, \f$\gamma^b_c = \delta^b_c + n^b n_c\f$, and \f$T_{a b}\f$ is the
245 : * stress-energy tensor if nonzero (if using the overload with no stress-energy
246 : * tensor provided, the stress energy term is omitted).
247 : *
248 : * To justify the stress-energy contribution to the F constraint, note that
249 : * the stress-energy tensor appears in the dynamics of the Generalized
250 : * Harmonic system only through \f$\partial_t \Pi_{a b}\f$.
251 : * That dependence arises from (using \f$\dots\f$ to indicate collections of
252 : * terms that are known to be independent of the stress-energy tensor):
253 : *
254 : * \f[
255 : * {\cal F}_a = \dots \alpha^{-1}(\partial_t {\cal C}_a),
256 : * \f]
257 : *
258 : * where
259 : *
260 : * \f[
261 : * {\cal C}_a = H_a + \gamma^{i j} \Phi_{ij a} + n^b \Pi_{ba}
262 : * - \frac{1}{2} \gamma_a{}^i g^{bc} \Phi_{i b c}
263 : * - \frac{1}{2} n_a g^{bc} \Pi_{b c}.
264 : * \f].
265 : *
266 : * Therefore, the Stress-energy contribution can be calculated from the
267 : * trace-reversed contribution appearing in
268 : * `grmhd::GhValenciaDivClean::add_stress_energy_term_to_dt_pi` -- the
269 : * trace reversal in that function and the trace-reversal that appears
270 : * explicitly in \f${\cal C}_a\f$ cancel.
271 : */
272 : template <typename DataType, size_t SpatialDim, typename Frame>
273 1 : tnsr::a<DataType, SpatialDim, Frame> f_constraint(
274 : const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
275 : const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
276 : const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
277 : const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
278 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
279 : const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
280 : const tnsr::aa<DataType, SpatialDim, Frame>& pi,
281 : const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
282 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
283 : const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
284 : const Scalar<DataType>& gamma2,
285 : const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint);
286 :
287 : template <typename DataType, size_t SpatialDim, typename Frame>
288 1 : void f_constraint(
289 : gsl::not_null<tnsr::a<DataType, SpatialDim, Frame>*> constraint,
290 : const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
291 : const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
292 : const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
293 : const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
294 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
295 : const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
296 : const tnsr::aa<DataType, SpatialDim, Frame>& pi,
297 : const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
298 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
299 : const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
300 : const Scalar<DataType>& gamma2,
301 : const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint);
302 :
303 : template <typename DataType, size_t SpatialDim, typename Frame>
304 1 : tnsr::a<DataType, SpatialDim, Frame> f_constraint(
305 : const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
306 : const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
307 : const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
308 : const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
309 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
310 : const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
311 : const tnsr::aa<DataType, SpatialDim, Frame>& pi,
312 : const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
313 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
314 : const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
315 : const Scalar<DataType>& gamma2,
316 : const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint,
317 : const tnsr::aa<DataType, SpatialDim, Frame>& trace_reversed_stress_energy);
318 :
319 : template <typename DataType, size_t SpatialDim, typename Frame>
320 1 : void f_constraint(
321 : gsl::not_null<tnsr::a<DataType, SpatialDim, Frame>*> constraint,
322 : const tnsr::a<DataType, SpatialDim, Frame>& gauge_function,
323 : const tnsr::ab<DataType, SpatialDim, Frame>& spacetime_d_gauge_function,
324 : const tnsr::a<DataType, SpatialDim, Frame>& spacetime_normal_one_form,
325 : const tnsr::A<DataType, SpatialDim, Frame>& spacetime_normal_vector,
326 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
327 : const tnsr::AA<DataType, SpatialDim, Frame>& inverse_spacetime_metric,
328 : const tnsr::aa<DataType, SpatialDim, Frame>& pi,
329 : const tnsr::iaa<DataType, SpatialDim, Frame>& phi,
330 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
331 : const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
332 : const Scalar<DataType>& gamma2,
333 : const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint,
334 : const tnsr::aa<DataType, SpatialDim, Frame>& trace_reversed_stress_energy);
335 : /// @}
336 :
337 : /// @{
338 : /*!
339 : * \brief Computes the generalized-harmonic (unnormalized) constraint energy.
340 : *
341 : * \details Computes the generalized-harmonic unnormalized constraint energy
342 : * [Eq. (53) of \cite Lindblom2005qh with \f$m^{ab}=\delta^{ab}\f$ and with each
343 : * term in the sum scaled by an arbitrary coefficient],
344 : * \f{eqnarray}{
345 : * E & = & K_1 C_a C_a + K_2\left(F_a F_a
346 : + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
347 : & + & K_3 C_{iab} C_{jab} \gamma^{ij} + K_4 C_{ikab} C_{jlab}\gamma^{ij}
348 : \gamma^{kl}.
349 : * \f}
350 : * Here \f$C_a\f$ is the gauge constraint, \f$F_a\f$ is the f constraint,
351 : * \f$C_{ia}\f$ is the two-index constraint, \f$C_{iab}\f$ is the
352 : * three-index constraint, \f$C_{ikab}\f$ is the four-index constraint,
353 : * \f$\gamma^{ij}\f$ is the inverse spatial metric, and
354 : * \f$K_1\f$, \f$K_2\f$, \f$K_3\f$, and \f$K_4\f$ are constant multipliers
355 : * for each term that each default to a value of 1.0. Note that in this
356 : * equation, spacetime indices \f$a,b\f$ are raised and lowered with
357 : * the Kronecker delta.
358 : *
359 : * Also note that the argument `four_index_constraint` is a rank-3 tensor.
360 : * This is because `gh::four_index_constraint()` takes
361 : * advantage of the antisymmetry of the four-index constraint's first two
362 : * indices to only compute and return the independent
363 : * components of \f$C_{ijab}\f$, which can be written as
364 : * \f{eqnarray}{
365 : * D_{iab} \equiv \frac{1}{2} \epsilon_{i}{}^{jk} C_{jkab},
366 : * \f} where \f$\epsilon_{ijk}\f$ is the flat-space Levi-Civita tensor,
367 : * whose inidces are raised and lowered with the Kronecker delta.
368 : * The result is
369 : * \f{eqnarray}{
370 : * E & = & K_1 C_a C_a + K_2\left(F_a F_a
371 : * + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
372 : * & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
373 : & + & 2 K_4 \gamma D_{iab} D_{jab} \gamma^{ij},
374 : * \f} where \f$\gamma\f$ is the determinant of the spatial metric.
375 : *
376 : * To derive this expression for the constraint energy implemented here,
377 : * Eq.~(53) of \cite Lindblom2005qh is
378 : * \f{eqnarray}{
379 : * S_{AB} dc^A dc^B &=&
380 : * m^{ab}\Bigl[d F_ad F_b
381 : * +\gamma^{ij}\bigl(d C_{ia}d C_{jb}
382 : * +\gamma^{kl}m^{cd}d C_{ikac}d C_{jlbd}\bigr)
383 : * \nonumber\\
384 : * & + & \Lambda^2\bigl(d C_ad C_b
385 : * +\gamma^{ij}m^{cd}d C_{iac}d C_{jbd}\bigr)
386 : * \Bigr].
387 : * \f} Replace \f$dc^A\rightarrow c^A\f$ to get
388 : * \f{eqnarray}{
389 : * E&=&
390 : * m^{ab}\Bigl[ F_a F_b
391 : * +\gamma^{ij}\bigl( C_{ia} C_{jb}
392 : * +\gamma^{kl}m^{cd} C_{ikac} C_{jlbd}\bigr)
393 : * \nonumber\\
394 : * & + & \Lambda^2\bigl( C_a C_b
395 : * +\gamma^{ij}m^{cd} C_{iac} C_{jbd}\bigr)
396 : * \Bigr]\nonumber\\
397 : * &=&
398 : * m^{ab} F_a F_b
399 : * +m^{ab}\gamma^{ij} C_{ia} C_{jb}
400 : * +m^{ab}\gamma^{ij} \gamma^{kl}m^{cd} C_{ikac} C_{jlbd}
401 : * \nonumber\\
402 : * & + & m^{ab}\Lambda^2 C_a C_b
403 : * +m^{ab}\Lambda^2 \gamma^{ij}m^{cd} C_{iac} C_{jbd}.
404 : * \f} Here \f$m^{ab}\f$ is an arbitrary positive-definite matrix, and
405 : * \f$\Lambda\f$ is an arbitrary real scalar.
406 : * Choose \f$m^{ab} = \delta^{ab}\f$ but allow an arbitrary coefficient to be
407 : * placed in front of each term. Then, absorb \f$\Lambda^2\f$ into one of
408 : * these coefficients, to get
409 : * \f{eqnarray}{ E &=& K_
410 : * F\delta^{ab} F_a F_b +K_2\delta^{ab}\gamma^{ij} C_{ia} C_{jb}
411 : +K_4\delta^{ab}\gamma^{ij}
412 : * \gamma^{kl}\delta^{cd} C_{ikac} C_{jlbd}
413 : * \nonumber\\
414 : * & + & K_1\delta^{ab} C_a C_b
415 : * +K_3\delta^{ab} \gamma^{ij}\delta^{cd} C_{iac} C_{jbd}.
416 : * \f}
417 : * Adopting a Euclidean norm for the constraint space (i.e., choosing to raise
418 : and
419 : * lower spacetime indices with Kronecker deltas) gives
420 : * \f{eqnarray}{ E &=& K_ F
421 : * F_a F_a +K_2\gamma^{ij} C_{ia} C_{ja} +K_4 \gamma^{ij} \gamma^{kl} C_{ikac}
422 : C_{jlac}
423 : * \nonumber\\
424 : * & + & K_1 C_a C_a
425 : * +K_3\gamma^{ij} C_{iac} C_{jac}.
426 : * \f} The two-index constraint and f constraint can be viewed as the
427 : * time and space components of a combined spacetime constraint. So next
428 : * choose
429 : * \f$K_ F=K_2\f$, giving \f{eqnarray}{ E&=& K_1 C_a C_a + K_2\left(F_a F_a
430 : * + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
431 : * & + & K_3 C_{iab} C_{jab} \gamma^{ij}
432 : * + K_4 C_{ikab} C_{jlab}\gamma^{ij} \gamma^{kl}.
433 : * \f}
434 : *
435 : * Note that \f$C_{ikab}\f$ is antisymmetric on the first two indices. Next,
436 : * replace the four-index constraint \f$C_{ijab}\f$ with \f$D_{iab}\f$, which
437 : * contains the independent components of \f$C_{ijab}\f$. Specifically,
438 : * \f{eqnarray}{
439 : * D_{iab} \equiv \frac{1}{2} \epsilon_{i}{}^{jk} C_{jkab}.
440 : * \f} The inverse relationship is
441 : * \f{eqnarray}{
442 : * C_{jkab} = \epsilon^{i}{}_{jk} D_{iab},
443 : * \f} where \f$\epsilon_{ijk}\f$ is the flat-space Levi-Civita tensor, whose
444 : * indices are raised and lowered with the Kronecker delta. Inserting this
445 : relation
446 : * to replace \f$C_{jkab}\f$ with \f$D_{iab}\f$ gives \f{eqnarray}{ E &=& K_1
447 : C_a
448 : * C_a + K_2\left(F_a F_a
449 : * + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
450 : * & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
451 : * & + & K_4 D_{mab} D_{nab} \epsilon^{m}{}_{ik}
452 : * \epsilon^{n}{}_{jl} \gamma^{ij} \gamma^{kl}. \f}
453 : *
454 : * There's a subtle point here: \f$\gamma^{ij}\f$ is the inverse spatial metric,
455 : which
456 : * is not necessarily flat. But \f$\epsilon^{i}{}_{jk}\f$ is the flat space
457 : * Levi-Civita tensor. In order to raise and lower indices of the Levi-Civita
458 : * tensor with the inverse spatial metrics, put in the appropriate factors of
459 : * \f$\sqrt{\gamma}\f$, where \f$\gamma\f$ is the metric determinant, to make
460 : the
461 : * curved-space Levi-Civita tensor compatible with \f$\gamma^{ij}\f$. Let
462 : * \f$\varepsilon^{ijk}\f$ represent the curved space Levi-Civita tensor
463 : compatible
464 : * with \f$\gamma^{ij}\f$: \f{eqnarray}{
465 : * \varepsilon^{mik} = \gamma^{-1/2} \epsilon^{mik}\\
466 : * \varepsilon_{mik} = \gamma^{1/2} \epsilon_{mik}.
467 : * \f} Then we can write the constraint energy as
468 : * \f{eqnarray}{
469 : * E &=& K_1 C_a C_a + K_2\left(F_a F_a
470 : * + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
471 : * & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
472 : * & + & K_4 D_{mab} D_{nab} \gamma \gamma^{-1/2}\epsilon^{m}{}_{ik}
473 : * \gamma^{-1/2}\epsilon^{n}{}_{jl} \gamma^{ij} \gamma^{kl}. \f} The factors of
474 : * \f$\gamma^{-1/2}\f$ make the Levi-Civita tensor compatible with
475 : \f$\gamma^{ij}\f$.
476 : * Swapping which summed indices are raised and which are lowered gives
477 : * \f{eqnarray}{ E &=& K_1 C_a
478 : C_a +
479 : * K_2\left(F_a F_a
480 : * + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
481 : * & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
482 : * & + & K_4 D_{mab} D_{nab} \gamma \gamma^{-1/2}\epsilon^{mik}
483 : \gamma^{-1/2}\epsilon^{njl}
484 : * \gamma_{ij} \gamma_{kl}, \f} or \f{eqnarray}{ E &=& K_1 C_a C_a +
485 : K_2\left(F_a F_a
486 : * + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
487 : * & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
488 : * & + & K_4 D_{mab} D_{nab} \gamma \varepsilon^{mik} \varepsilon^{njl}
489 : \gamma_{ij}
490 : * \gamma_{kl}, \f} or, reversing up and down repeated indices again,
491 : * \f{eqnarray}{ E
492 : * &=& K_1 C_a C_a + K_2\left(F_a F_a
493 : * + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
494 : * & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
495 : * & + & K_4 D_{mab} D_{nab} \gamma \varepsilon^{m}{}_{ik}
496 : \varepsilon^{n}{}_{jl}
497 : * \gamma^{ij} \gamma^{kl}. \f}
498 : *
499 : * The metric raises and lowers the indices of \f$\varepsilon^{ijk}\f$,
500 : * so this can
501 : * be written as \f{eqnarray}{ E &=& K_1 C_a C_a + K_2\left(F_a F_a
502 : * + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
503 : * & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
504 : * & + & K_4 \gamma D_{mab} D^{n}{}_{ab} \varepsilon^{mjl}
505 : \varepsilon_{njl}.
506 : * \f}
507 : *
508 : * Now, in flat space (Eq. (1.23) of \cite ThorneBlandford2017),
509 : * \f{eqnarray}{
510 : * \epsilon^{mjl} \epsilon_{njl} = \delta^{mj}_{nj} = \delta^m_n \delta^j_j -
511 : * \delta^m_j \delta^j_n = 2 \delta^m_n. \f} But this holds for curved space
512 : * as well: multiply the left hand side by \f$1 = \gamma^{1/2} \gamma^{-1/2}\f$
513 : to get
514 : * \f{eqnarray}{
515 : * \gamma^{-1/2}\epsilon^{mjl} \gamma^{1/2}\epsilon_{njl} = \varepsilon^{mjl}
516 : * \varepsilon_{njl} = \delta^{mj}_{nj} = \delta^m_n \delta^j_j - \delta^m_j
517 : * \delta^j_n = 2 \delta^m_n. \f} So the constraint energy is \f{eqnarray}{ E
518 : &=&
519 : * K_1 C_a C_a + K_2\left(F_a F_a
520 : * + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
521 : * & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
522 : * & + & 2 K_4 D_{mab} D^{n}{}_{ab} \delta^m_n.
523 : * \f}
524 : * Simplifying gives the formula implemented here:
525 : * \f{eqnarray}{
526 : * E &=& K_1 C_a C_a + K_2\left(F_a F_a
527 : * + C_{ia} C_{ja} \gamma^{ij}\right)\nonumber\\
528 : * & + & K_3 C_{iab} C_{jab} \gamma^{ij}\nonumber\\
529 : * & + & 2 K_4 \gamma D_{iab} D_{jab} \gamma^{ij}.
530 : * \f}
531 : */
532 : template <typename DataType, size_t SpatialDim, typename Frame>
533 1 : Scalar<DataType> constraint_energy(
534 : const tnsr::a<DataType, SpatialDim, Frame>& gauge_constraint,
535 : const tnsr::a<DataType, SpatialDim, Frame>& f_constraint,
536 : const tnsr::ia<DataType, SpatialDim, Frame>& two_index_constraint,
537 : const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint,
538 : const tnsr::iaa<DataType, SpatialDim, Frame>& four_index_constraint,
539 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
540 : const Scalar<DataType>& spatial_metric_determinant,
541 : double gauge_constraint_multiplier = 1.0,
542 : double two_index_constraint_multiplier = 1.0,
543 : double three_index_constraint_multiplier = 1.0,
544 : double four_index_constraint_multiplier = 1.0);
545 :
546 : template <typename DataType, size_t SpatialDim, typename Frame>
547 1 : void constraint_energy(
548 : gsl::not_null<Scalar<DataType>*> energy,
549 : const tnsr::a<DataType, SpatialDim, Frame>& gauge_constraint,
550 : const tnsr::a<DataType, SpatialDim, Frame>& f_constraint,
551 : const tnsr::ia<DataType, SpatialDim, Frame>& two_index_constraint,
552 : const tnsr::iaa<DataType, SpatialDim, Frame>& three_index_constraint,
553 : const tnsr::iaa<DataType, SpatialDim, Frame>& four_index_constraint,
554 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
555 : const Scalar<DataType>& spatial_metric_determinant,
556 : double gauge_constraint_multiplier = 1.0,
557 : double two_index_constraint_multiplier = 1.0,
558 : double three_index_constraint_multiplier = 1.0,
559 : double four_index_constraint_multiplier = 1.0);
560 : /// @}
561 :
562 : /// @{
563 : /*!
564 : * \brief Computes the generalized-harmonic normalized constraint energy.
565 : *
566 : * \details Computes the generalized-harmonic normalized constraint energy
567 : * integrand [Eq. (70) of \cite Lindblom2005qh with \f$m^{ab}=\delta^{ab}\f$],
568 : * \f{eqnarray}{
569 : * ||E||=\gamma^{ij}\delta^{ab}\delta^{cd}
570 : * (\Lambda^{2}\partial_{i}g_{ac}\partial_{j}g_{bd}
571 : * + \partial_{i}\Pi_{ac}\partial_{j}\Pi_{bd} +
572 : * \gamma^{kl}\partial_{i}\Phi_{kac}\partial_{j}\Phi_{lbd})\gamma^{1/2}
573 : * \f}
574 : *
575 : * Here \f$\gamma^{ij}\f$ is the inverse spatial metric, and \f$\Lambda^{2}\f$
576 : * is the squared dimensional constant. Note
577 : * that in this equation, spacetime indices \f$a,b\f$ are raised and lowered
578 : * with the Kronecker delta.
579 : */
580 : template <typename DataType, size_t SpatialDim, typename Frame>
581 1 : Scalar<DataType> constraint_energy_normalization(
582 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_spacetime_metric,
583 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
584 : const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
585 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
586 : const Scalar<DataType>& sqrt_spatial_metric_determinant,
587 : double dimensional_constant);
588 :
589 : template <typename DataType, size_t SpatialDim, typename Frame>
590 1 : void constraint_energy_normalization(
591 : gsl::not_null<Scalar<DataType>*> energy_norm,
592 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_spacetime_metric,
593 : const tnsr::iaa<DataType, SpatialDim, Frame>& d_pi,
594 : const tnsr::ijaa<DataType, SpatialDim, Frame>& d_phi,
595 : const tnsr::II<DataType, SpatialDim, Frame>& inverse_spatial_metric,
596 : const Scalar<DataType>& sqrt_spatial_metric_determinant,
597 : double dimensional_constant);
598 : /// @}
599 :
600 : namespace Tags {
601 : /*!
602 : * \brief Compute item to get the gauge constraint for the
603 : * generalized harmonic evolution system.
604 : *
605 : * \details See `gauge_constraint()`. Can be retrieved using
606 : * `gh::Tags::GaugeConstraint`.
607 : */
608 : template <size_t SpatialDim, typename Frame>
609 1 : struct GaugeConstraintCompute : GaugeConstraint<DataVector, SpatialDim, Frame>,
610 : db::ComputeTag {
611 0 : using argument_tags = tmpl::list<
612 : GaugeH<DataVector, SpatialDim, Frame>,
613 : gr::Tags::SpacetimeNormalOneForm<DataVector, SpatialDim, Frame>,
614 : gr::Tags::SpacetimeNormalVector<DataVector, SpatialDim, Frame>,
615 : gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
616 : gr::Tags::InverseSpacetimeMetric<DataVector, SpatialDim, Frame>,
617 : Pi<DataVector, SpatialDim, Frame>, Phi<DataVector, SpatialDim, Frame>>;
618 :
619 0 : using return_type = tnsr::a<DataVector, SpatialDim, Frame>;
620 :
621 0 : static constexpr auto function = static_cast<void (*)(
622 : gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame>*>,
623 : const tnsr::a<DataVector, SpatialDim, Frame>&,
624 : const tnsr::a<DataVector, SpatialDim, Frame>&,
625 : const tnsr::A<DataVector, SpatialDim, Frame>&,
626 : const tnsr::II<DataVector, SpatialDim, Frame>&,
627 : const tnsr::AA<DataVector, SpatialDim, Frame>&,
628 : const tnsr::aa<DataVector, SpatialDim, Frame>&,
629 : const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
630 : &gauge_constraint<DataVector, SpatialDim, Frame>);
631 :
632 0 : using base = GaugeConstraint<DataVector, SpatialDim, Frame>;
633 : };
634 :
635 : /*!
636 : * \brief Compute item to get the F-constraint for the
637 : * generalized harmonic evolution system.
638 : *
639 : * \details See `f_constraint()`. Can be retrieved using
640 : * `gh::Tags::FConstraint`.
641 : *
642 : * \note If the system contains matter, you will need to use a system-specific
643 : * version of this compute tag that passes the appropriate stress-energy tensor
644 : * to the F-constraint calculation.
645 : */
646 : template <size_t SpatialDim, typename Frame>
647 1 : struct FConstraintCompute : FConstraint<DataVector, SpatialDim, Frame>,
648 : db::ComputeTag {
649 0 : using argument_tags = tmpl::list<
650 : GaugeH<DataVector, SpatialDim, Frame>,
651 : SpacetimeDerivGaugeH<DataVector, SpatialDim, Frame>,
652 : gr::Tags::SpacetimeNormalOneForm<DataVector, SpatialDim, Frame>,
653 : gr::Tags::SpacetimeNormalVector<DataVector, SpatialDim, Frame>,
654 : gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
655 : gr::Tags::InverseSpacetimeMetric<DataVector, SpatialDim, Frame>,
656 : Pi<DataVector, SpatialDim, Frame>, Phi<DataVector, SpatialDim, Frame>,
657 : ::Tags::deriv<Pi<DataVector, SpatialDim, Frame>, tmpl::size_t<SpatialDim>,
658 : Frame>,
659 : ::Tags::deriv<Phi<DataVector, SpatialDim, Frame>,
660 : tmpl::size_t<SpatialDim>, Frame>,
661 : ::gh::Tags::ConstraintGamma2,
662 : ThreeIndexConstraint<DataVector, SpatialDim, Frame>>;
663 :
664 0 : using return_type = tnsr::a<DataVector, SpatialDim, Frame>;
665 :
666 0 : static constexpr auto function = static_cast<void (*)(
667 : gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame>*>,
668 : const tnsr::a<DataVector, SpatialDim, Frame>&,
669 : const tnsr::ab<DataVector, SpatialDim, Frame>&,
670 : const tnsr::a<DataVector, SpatialDim, Frame>&,
671 : const tnsr::A<DataVector, SpatialDim, Frame>&,
672 : const tnsr::II<DataVector, SpatialDim, Frame>&,
673 : const tnsr::AA<DataVector, SpatialDim, Frame>&,
674 : const tnsr::aa<DataVector, SpatialDim, Frame>&,
675 : const tnsr::iaa<DataVector, SpatialDim, Frame>&,
676 : const tnsr::iaa<DataVector, SpatialDim, Frame>&,
677 : const tnsr::ijaa<DataVector, SpatialDim, Frame>&,
678 : const Scalar<DataVector>&,
679 : const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
680 : &f_constraint<DataVector, SpatialDim, Frame>);
681 :
682 0 : using base = FConstraint<DataVector, SpatialDim, Frame>;
683 : };
684 :
685 : /*!
686 : * \brief Compute item to get the two-index constraint for the
687 : * generalized harmonic evolution system.
688 : *
689 : * \details See `two_index_constraint()`. Can be retrieved using
690 : * `gh::Tags::TwoIndexConstraint`.
691 : */
692 : template <size_t SpatialDim, typename Frame>
693 1 : struct TwoIndexConstraintCompute
694 : : TwoIndexConstraint<DataVector, SpatialDim, Frame>,
695 : db::ComputeTag {
696 0 : using argument_tags = tmpl::list<
697 : SpacetimeDerivGaugeH<DataVector, SpatialDim, Frame>,
698 : gr::Tags::SpacetimeNormalOneForm<DataVector, SpatialDim, Frame>,
699 : gr::Tags::SpacetimeNormalVector<DataVector, SpatialDim, Frame>,
700 : gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
701 : gr::Tags::InverseSpacetimeMetric<DataVector, SpatialDim, Frame>,
702 : Pi<DataVector, SpatialDim, Frame>, Phi<DataVector, SpatialDim, Frame>,
703 : ::Tags::deriv<Pi<DataVector, SpatialDim, Frame>, tmpl::size_t<SpatialDim>,
704 : Frame>,
705 : ::Tags::deriv<Phi<DataVector, SpatialDim, Frame>,
706 : tmpl::size_t<SpatialDim>, Frame>,
707 : ::gh::Tags::ConstraintGamma2,
708 : ThreeIndexConstraint<DataVector, SpatialDim, Frame>>;
709 :
710 0 : using return_type = tnsr::ia<DataVector, SpatialDim, Frame>;
711 :
712 0 : static constexpr auto function = static_cast<void (*)(
713 : gsl::not_null<tnsr::ia<DataVector, SpatialDim, Frame>*>,
714 : const tnsr::ab<DataVector, SpatialDim, Frame>&,
715 : const tnsr::a<DataVector, SpatialDim, Frame>&,
716 : const tnsr::A<DataVector, SpatialDim, Frame>&,
717 : const tnsr::II<DataVector, SpatialDim, Frame>&,
718 : const tnsr::AA<DataVector, SpatialDim, Frame>&,
719 : const tnsr::aa<DataVector, SpatialDim, Frame>&,
720 : const tnsr::iaa<DataVector, SpatialDim, Frame>&,
721 : const tnsr::iaa<DataVector, SpatialDim, Frame>&,
722 : const tnsr::ijaa<DataVector, SpatialDim, Frame>&,
723 : const Scalar<DataVector>&,
724 : const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
725 : &two_index_constraint<DataVector, SpatialDim, Frame>);
726 :
727 0 : using base = TwoIndexConstraint<DataVector, SpatialDim, Frame>;
728 : };
729 :
730 : /*!
731 : * \brief Compute item to get the three-index constraint for the
732 : * generalized harmonic evolution system.
733 : *
734 : * \details See `three_index_constraint()`. Can be retrieved using
735 : * `gh::Tags::ThreeIndexConstraint`.
736 : */
737 : template <size_t SpatialDim, typename Frame>
738 1 : struct ThreeIndexConstraintCompute
739 : : ThreeIndexConstraint<DataVector, SpatialDim, Frame>,
740 : db::ComputeTag {
741 0 : using argument_tags = tmpl::list<
742 : ::Tags::deriv<gr::Tags::SpacetimeMetric<DataVector, SpatialDim, Frame>,
743 : tmpl::size_t<SpatialDim>, Frame>,
744 : Phi<DataVector, SpatialDim, Frame>>;
745 :
746 0 : using return_type = tnsr::iaa<DataVector, SpatialDim, Frame>;
747 :
748 0 : static constexpr auto function = static_cast<void (*)(
749 : gsl::not_null<tnsr::iaa<DataVector, SpatialDim, Frame>*>,
750 : const tnsr::iaa<DataVector, SpatialDim, Frame>&,
751 : const tnsr::iaa<DataVector, SpatialDim, Frame>&)>(
752 : &three_index_constraint<DataVector, SpatialDim, Frame>);
753 :
754 0 : using base = ThreeIndexConstraint<DataVector, SpatialDim, Frame>;
755 : };
756 :
757 : /*!
758 : * \brief Compute item to get the four-index constraint for the
759 : * generalized harmonic evolution system.
760 : *
761 : * \details See `four_index_constraint()`. Can be retrieved using
762 : * `gh::Tags::FourIndexConstraint`.
763 : */
764 : template <size_t SpatialDim, typename Frame>
765 1 : struct FourIndexConstraintCompute
766 : : FourIndexConstraint<DataVector, SpatialDim, Frame>,
767 : db::ComputeTag {
768 0 : using argument_tags =
769 : tmpl::list<::Tags::deriv<Phi<DataVector, SpatialDim, Frame>,
770 : tmpl::size_t<SpatialDim>, Frame>>;
771 :
772 0 : using return_type = tnsr::iaa<DataVector, SpatialDim, Frame>;
773 :
774 0 : static constexpr auto function = static_cast<void (*)(
775 : gsl::not_null<tnsr::iaa<DataVector, SpatialDim, Frame>*>,
776 : const tnsr::ijaa<DataVector, SpatialDim, Frame>&)>(
777 : &four_index_constraint<DataVector, SpatialDim, Frame>);
778 :
779 0 : using base = FourIndexConstraint<DataVector, SpatialDim, Frame>;
780 : };
781 :
782 : /*!
783 : * \brief Compute item to get combined energy in all constraints for the
784 : * generalized harmonic evolution system.
785 : *
786 : * \details See `constraint_energy()`. Can be retrieved using
787 : * `gh::Tags::ConstraintEnergy`.
788 : */
789 : template <size_t SpatialDim, typename Frame>
790 1 : struct ConstraintEnergyCompute
791 : : ConstraintEnergy<DataVector, SpatialDim, Frame>,
792 : db::ComputeTag {
793 0 : using argument_tags =
794 : tmpl::list<GaugeConstraint<DataVector, SpatialDim, Frame>,
795 : FConstraint<DataVector, SpatialDim, Frame>,
796 : TwoIndexConstraint<DataVector, SpatialDim, Frame>,
797 : ThreeIndexConstraint<DataVector, SpatialDim, Frame>,
798 : FourIndexConstraint<DataVector, SpatialDim, Frame>,
799 : gr::Tags::InverseSpatialMetric<DataVector, SpatialDim, Frame>,
800 : gr::Tags::DetSpatialMetric<DataVector>>;
801 :
802 0 : using return_type = Scalar<DataVector>;
803 :
804 0 : static constexpr auto function(
805 : const gsl::not_null<Scalar<DataVector>*> energy,
806 : const tnsr::a<DataVector, SpatialDim, Frame>& gauge_constraint,
807 : const tnsr::a<DataVector, SpatialDim, Frame>& f_constraint,
808 : const tnsr::ia<DataVector, SpatialDim, Frame>& two_index_constraint,
809 : const tnsr::iaa<DataVector, SpatialDim, Frame>& three_index_constraint,
810 : const tnsr::iaa<DataVector, SpatialDim, Frame>& four_index_constraint,
811 : const tnsr::II<DataVector, SpatialDim, Frame>& inverse_spatial_metric,
812 : const Scalar<DataVector>& spatial_metric_determinant) {
813 : set_number_of_grid_points(energy, spatial_metric_determinant);
814 : constraint_energy<DataVector, SpatialDim, Frame>(
815 : energy, gauge_constraint, f_constraint, two_index_constraint,
816 : three_index_constraint, four_index_constraint, inverse_spatial_metric,
817 : spatial_metric_determinant);
818 : }
819 :
820 0 : using base = ConstraintEnergy<DataVector, SpatialDim, Frame>;
821 : };
822 : } // namespace Tags
823 : } // namespace gh
|