VerifyGrSolution.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
7 
8 #include <array>
9 #include <cstddef>
10 
12 #include "DataStructures/DataBox/Prefixes.hpp" // IWYU pragma: keep
13 #include "DataStructures/DataVector.hpp" // IWYU pragma: keep
19 #include "Domain/CoordinateMaps/CoordinateMap.tpp"
21 #include "Domain/CoordinateMaps/ProductMaps.tpp"
23 #include "Domain/Mesh.hpp"
26 #include "Evolution/Systems/GeneralizedHarmonic/Tags.hpp"
27 #include "Evolution/TypeTraits.hpp" // IWYU pragma: keep
29 #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.tpp"
34 #include "PointwiseFunctions/GeneralRelativity/IndexManipulation.hpp"
35 #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
37 #include "Utilities/Gsl.hpp"
40 #include "Utilities/TMPL.hpp"
41 #include "Utilities/TypeTraits.hpp"
42 
43 /// \cond
44 // IWYU pragma: no_forward_declare Tensor
45 // IWYU pragma: no_forward_declare Tags::deriv
46 /// \endcond
47 
48 namespace TestHelpers {
49 /// \ingroup TestingFrameworkGroup
50 /// Functions for testing GR analytic solutions
51 namespace VerifyGrSolution {
52 
53 /// Determines if the given `solution` is a time-independent solution
54 /// of the Einstein equations. Uses numerical derivatives to compute
55 /// the solution, on a grid extending from `lower_bound` to `upper_bound`
56 /// with `grid_size_each_dimension` points in each dimension.
57 /// The right-hand side of the Einstein equations must be zero within
58 /// `error_tolerance`
59 template <typename Solution>
61  const Solution& solution, const size_t grid_size_each_dimension,
62  const std::array<double, 3>& lower_bound,
63  const std::array<double, 3>& upper_bound,
64  const double error_tolerance) noexcept {
65  static_assert(evolution::is_analytic_solution_v<Solution>,
66  "Solution was not derived from AnalyticSolution");
67  // Shorter names for tags.
68  using SpacetimeMetric = gr::Tags::SpacetimeMetric<3, Frame::Inertial>;
72  using VariablesTags = tmpl::list<SpacetimeMetric, Pi, Phi, GaugeH>;
73 
74  // Set up grid
75  const size_t data_size = pow<3>(grid_size_each_dimension);
76  Mesh<3> mesh{grid_size_each_dimension, Spectral::Basis::Legendre,
77  Spectral::Quadrature::GaussLobatto};
78 
79  using Affine = domain::CoordinateMaps::Affine;
80  using Affine3D =
82  const auto coord_map =
83  domain::make_coordinate_map<Frame::Logical, Frame::Inertial>(Affine3D{
84  Affine{-1., 1., lower_bound[0], upper_bound[0]},
85  Affine{-1., 1., lower_bound[1], upper_bound[1]},
86  Affine{-1., 1., lower_bound[2], upper_bound[2]},
87  });
88 
89  // Set up coordinates
90  const auto x_logical = logical_coordinates(mesh);
91  const auto x = coord_map(x_logical);
92  const double t = 1.3; // Arbitrary time for time-independent solution.
93 
94  // Evaluate analytic solution
95  const auto vars =
96  solution.variables(x, t, typename Solution::template tags<DataVector>{});
97  const auto& lapse = get<gr::Tags::Lapse<>>(vars);
98  const auto& dt_lapse = get<Tags::dt<gr::Tags::Lapse<>>>(vars);
99  const auto& d_lapse =
100  get<typename Solution::template DerivLapse<DataVector>>(vars);
101  const auto& shift = get<gr::Tags::Shift<3>>(vars);
102  const auto& d_shift =
103  get<typename Solution::template DerivShift<DataVector>>(vars);
104  const auto& dt_shift = get<Tags::dt<gr::Tags::Shift<3>>>(vars);
105  const auto& g = get<gr::Tags::SpatialMetric<3>>(vars);
106  const auto& dt_g = get<Tags::dt<gr::Tags::SpatialMetric<3>>>(vars);
107  const auto& d_g =
108  get<typename Solution::template DerivSpatialMetric<DataVector>>(vars);
109 
110  // Check those quantities that should vanish identically.
111  CHECK(get(dt_lapse) == make_with_value<DataVector>(x, 0.));
112  CHECK(dt_shift ==
113  make_with_value<cpp20::remove_cvref_t<decltype(dt_shift)>>(x, 0.));
114  CHECK(dt_g == make_with_value<cpp20::remove_cvref_t<decltype(dt_g)>>(x, 0.));
115 
116  // Need upper spatial metric for many things below.
117  const auto upper_spatial_metric = determinant_and_inverse(g).second;
118 
119  // Compute generalized harmonic quantities. Put them in a Variables
120  // so that we can take numerical derivatives of them.
121  // Also put gauge_function into this list since we need a numerical
122  // derivative of it too.
123  Variables<VariablesTags> gh_vars(data_size);
124  auto& psi = get<SpacetimeMetric>(gh_vars);
125  auto& pi = get<Pi>(gh_vars);
126  auto& phi = get<Phi>(gh_vars);
127  auto& gauge_function = get<GaugeH>(gh_vars);
128  psi = gr::spacetime_metric(lapse, shift, g);
129  phi = GeneralizedHarmonic::phi(lapse, d_lapse, shift, d_shift, g, d_g);
130  pi = GeneralizedHarmonic::pi(lapse, dt_lapse, shift, dt_shift, g, dt_g, phi);
131 
132  // Compute gauge_function compatible with d/dt(lapse) and d/dt(shift).
133  gauge_function = GeneralizedHarmonic::gauge_source(
134  lapse, dt_lapse, d_lapse, shift, dt_shift, d_shift, g,
135  trace(gr::extrinsic_curvature(lapse, shift, d_shift, g, dt_g, d_g),
136  upper_spatial_metric),
138  upper_spatial_metric));
139 
140  // Compute numerical derivatives of psi,pi,phi,H.
141  // Normally one should not take numerical derivatives of H for
142  // plugging into the RHS of the generalized harmonic equations, but
143  // here this is just a test.
144  const auto gh_derivs =
145  partial_derivatives<VariablesTags, VariablesTags, 3, Frame::Inertial>(
146  gh_vars, mesh, coord_map.inv_jacobian(x_logical));
147  const auto& d_psi =
148  get<Tags::deriv<SpacetimeMetric, tmpl::size_t<3>, Frame::Inertial>>(
149  gh_derivs);
150  const auto& d_pi =
151  get<Tags::deriv<Pi, tmpl::size_t<3>, Frame::Inertial>>(gh_derivs);
152  const auto& d_phi =
153  get<Tags::deriv<Phi, tmpl::size_t<3>, Frame::Inertial>>(gh_derivs);
154  const auto& d_H =
155  get<Tags::deriv<GaugeH, tmpl::size_t<3>, Frame::Inertial>>(gh_derivs);
156 
157  Approx numerical_approx =
158  Approx::custom().epsilon(error_tolerance).scale(1.0);
159 
160  // Test 3-index constraint
161  CHECK_ITERABLE_CUSTOM_APPROX(d_psi, phi, numerical_approx);
162 
163  // Compute spacetime deriv of H.
164  // Assume time derivative of H is zero, for time-independent solution
165  auto d4_H = make_with_value<tnsr::ab<DataVector, 3>>(x, 0.0);
166  for (size_t a = 0; a < 4; ++a) {
167  for (size_t i = 0; i < 3; ++i) {
168  d4_H.get(i + 1, a) = d_H.get(i, a);
169  }
170  }
171 
172  // Compute analytic derivatives of psi, for use in computing
173  // christoffel symbols.
174  auto d4_psi = make_with_value<tnsr::abb<DataVector, 3>>(x, 0.0);
175  for (size_t b = 0; b < 4; ++b) {
176  for (size_t c = b; c < 4; ++c) { // symmetry
177  d4_psi.get(0, b, c) = -get(lapse) * pi.get(b, c);
178  for (size_t k = 0; k < 3; ++k) {
179  d4_psi.get(0, b, c) += shift.get(k) * phi.get(k, b, c);
180  d4_psi.get(k + 1, b, c) = phi.get(k, b, c);
181  }
182  }
183  }
184 
185  // Compute derived spacetime quantities
186  const auto upper_psi =
187  gr::inverse_spacetime_metric(lapse, shift, upper_spatial_metric);
189  const auto christoffel_second_kind =
191  const auto trace_christoffel_first_kind =
193  const auto normal_one_form =
194  gr::spacetime_normal_one_form<3, Frame::Inertial>(lapse);
195  const auto normal_vector = gr::spacetime_normal_vector(lapse, shift);
196 
197  // Test ADM evolution equation gives zero
198  auto dt_g_adm = make_with_value<tnsr::ii<DataVector, 3>>(x, 0.0);
199  {
200  auto ex_curv = gr::extrinsic_curvature(lapse, shift, d_shift, g, dt_g, d_g);
201  for (size_t i = 0; i < 3; ++i) {
202  for (size_t j = i; j < 3; ++j) { // Symmetry
203  dt_g_adm.get(i, j) -= 2.0 * get(lapse) * ex_curv.get(i, j);
204  for (size_t k = 0; k < 3; ++k) {
205  dt_g_adm.get(i, j) += shift.get(k) * d_g.get(k, i, j) +
206  g.get(k, i) * d_shift.get(j, k) +
207  g.get(k, j) * d_shift.get(i, k);
208  }
209  }
210  }
211  CHECK_ITERABLE_APPROX(dt_g_adm,
212  make_with_value<decltype(dt_g_adm)>(x, 0.0));
213  }
214 
215  // Test 1-index constraint
217  gauge_function, normal_one_form, normal_vector, upper_spatial_metric,
218  upper_psi, pi, phi);
219  CHECK_ITERABLE_CUSTOM_APPROX(C_1, make_with_value<decltype(C_1)>(x, 0.0),
220  numerical_approx);
221 
222  // Constraint-damping parameters: Set to arbitrary values.
223  // gamma = 0 (for all gammas) and gamma1 = -1 are special because,
224  // they zero out various terms in the equations, so don't choose those.
225  const auto gamma0 = make_with_value<Scalar<DataVector>>(x, 1.0);
226  const auto gamma1 = make_with_value<Scalar<DataVector>>(x, 1.0);
227  const auto gamma2 = make_with_value<Scalar<DataVector>>(x, 1.0);
228 
229  // Compute RHS of generalized harmonic Einstein equations.
230  auto dt_psi =
231  make_with_value<tnsr::aa<DataVector, 3, Frame::Inertial>>(x, 0.0);
232  auto dt_pi =
233  make_with_value<tnsr::aa<DataVector, 3, Frame::Inertial>>(x, 0.0);
234  auto dt_phi =
235  make_with_value<tnsr::iaa<DataVector, 3, Frame::Inertial>>(x, 0.0);
237  make_not_null(&dt_psi), make_not_null(&dt_pi), make_not_null(&dt_phi),
238  psi, pi, phi, d_psi, d_pi, d_phi, gamma0, gamma1, gamma2, gauge_function,
239  d4_H, lapse, shift, upper_spatial_metric, upper_psi,
240  trace_christoffel_first_kind, christoffel_first_kind,
241  christoffel_second_kind, normal_vector, normal_one_form);
242 
243  // Make sure the RHS is zero.
245  dt_psi, make_with_value<decltype(dt_psi)>(x, 0.0), numerical_approx);
246  CHECK_ITERABLE_CUSTOM_APPROX(dt_pi, make_with_value<decltype(dt_pi)>(x, 0.0),
247  numerical_approx);
249  dt_phi, make_with_value<decltype(dt_phi)>(x, 0.0), numerical_approx);
250 }
251 
252 namespace detail {
253 template <typename Tag>
255 
256 template <typename Tag, typename Solution>
257 db::const_item_type<Tag> time_derivative(const Solution& solution,
258  const tnsr::I<double, 3>& x,
259  const double time,
260  const double dt) noexcept {
261  db::const_item_type<Tag> result{};
262  for (auto it = result.begin(); it != result.end(); ++it) {
263  const auto index = result.get_tensor_index(it);
264  *it = numerical_derivative(
265  [&index, &solution, &x](const std::array<double, 1>& t_array) noexcept {
266  return std::array<double, 1>{
267  {get<Tag>(solution.variables(x, t_array[0], tmpl::list<Tag>{}))
268  .get(index)}};
269  },
270  std::array<double, 1>{{time}}, 0, dt)[0];
271  }
272  return result;
273 }
274 
275 template <typename Tag, typename Solution>
276 db::const_item_type<deriv<Tag>> space_derivative(const Solution& solution,
277  const tnsr::I<double, 3>& x,
278  const double time,
279  const double dx) noexcept {
281  for (auto it = result.begin(); it != result.end(); ++it) {
282  const auto index = result.get_tensor_index(it);
283  *it =
284  numerical_derivative([&index, &solution, &time, &x](
285  const std::array<double, 1>& offset) noexcept {
286  auto position = x;
287  position.get(index[0]) += offset[0];
288  return std::array<double, 1>{
289  {get<Tag>(solution.variables(position, time, tmpl::list<Tag>{}))
290  .get(all_but_specified_element_of(index, 0))}};
291  },
292  std::array<double, 1>{{0.0}}, 0, dx)[0];
293  }
294  return result;
295 }
296 } // namespace detail
297 
298 /// Check the consistency of dependent quantities returned by a
299 /// solution. This includes checking pointwise relations such as
300 /// consistency of the metric and inverse and comparing returned and
301 /// numerical derivatives.
302 template <typename Solution>
303 void verify_consistency(const Solution& solution, const double time,
304  const tnsr::I<double, 3>& position,
305  const double derivative_delta,
306  const double derivative_tolerance) noexcept {
307  using Lapse = gr::Tags::Lapse<double>;
310  using SqrtDetSpatialMetric = gr::Tags::SqrtDetSpatialMetric<double>;
311  using InverseSpatialMetric =
313  using ExtrinsicCurvature =
315  using tags =
316  tmpl::list<SpatialMetric, SqrtDetSpatialMetric, InverseSpatialMetric,
317  ExtrinsicCurvature, Lapse, Shift, detail::deriv<Shift>,
320 
321  auto derivative_approx = approx.epsilon(derivative_tolerance);
322 
323  const auto vars = solution.variables(position, time, tags{});
324 
325  const auto numerical_metric_det_and_inverse =
326  determinant_and_inverse(get<SpatialMetric>(vars));
327  CHECK_ITERABLE_APPROX(get(get<SqrtDetSpatialMetric>(vars)),
328  sqrt(get(numerical_metric_det_and_inverse.first)));
329  CHECK_ITERABLE_APPROX(get<InverseSpatialMetric>(vars),
330  numerical_metric_det_and_inverse.second);
331 
333  get<ExtrinsicCurvature>(vars),
335  get<Lapse>(vars), get<Shift>(vars), get<detail::deriv<Shift>>(vars),
336  get<SpatialMetric>(vars), get<Tags::dt<SpatialMetric>>(vars),
337  get<detail::deriv<SpatialMetric>>(vars)));
338 
339  CHECK_ITERABLE_CUSTOM_APPROX(get<Tags::dt<Lapse>>(vars),
340  detail::time_derivative<Lapse>(
341  solution, position, time, derivative_delta),
342  derivative_approx);
343  CHECK_ITERABLE_CUSTOM_APPROX(get<Tags::dt<Shift>>(vars),
344  detail::time_derivative<Shift>(
345  solution, position, time, derivative_delta),
346  derivative_approx);
347  CHECK_ITERABLE_CUSTOM_APPROX(get<Tags::dt<SpatialMetric>>(vars),
348  detail::time_derivative<SpatialMetric>(
349  solution, position, time, derivative_delta),
350  derivative_approx);
351 
352  CHECK_ITERABLE_CUSTOM_APPROX(get<detail::deriv<Lapse>>(vars),
353  detail::space_derivative<Lapse>(
354  solution, position, time, derivative_delta),
355  derivative_approx);
356  CHECK_ITERABLE_CUSTOM_APPROX(get<detail::deriv<Shift>>(vars),
357  detail::space_derivative<Shift>(
358  solution, position, time, derivative_delta),
359  derivative_approx);
360  CHECK_ITERABLE_CUSTOM_APPROX(get<detail::deriv<SpatialMetric>>(vars),
361  detail::space_derivative<SpatialMetric>(
362  solution, position, time, derivative_delta),
363  derivative_approx);
364 }
365 } // namespace VerifyGrSolution
366 } // namespace TestHelpers
tnsr::ii< DataType, SpatialDim, Frame > extrinsic_curvature(const Scalar< DataType > &lapse, const tnsr::I< DataType, SpatialDim, Frame > &shift, const tnsr::iJ< DataType, SpatialDim, Frame > &deriv_shift, const tnsr::ii< DataType, SpatialDim, Frame > &spatial_metric, const tnsr::ii< DataType, SpatialDim, Frame > &dt_spatial_metric, const tnsr::ijj< DataType, SpatialDim, Frame > &deriv_spatial_metric) noexcept
Computes extrinsic curvature from metric and derivatives.
Auxiliary variable which is analytically the spatial derivative of the spacetime metric.
Definition: Tags.hpp:40
Defines function computing the determinant and inverse of a tensor.
Definition: TestCreation.hpp:14
void phi(gsl::not_null< tnsr::iaa< DataType, SpatialDim, Frame > *> phi, const Scalar< DataType > &lapse, const tnsr::i< DataType, SpatialDim, Frame > &deriv_lapse, const tnsr::I< DataType, SpatialDim, Frame > &shift, const tnsr::iJ< DataType, SpatialDim, Frame > &deriv_shift, const tnsr::ii< DataType, SpatialDim, Frame > &spatial_metric, const tnsr::ijj< DataType, SpatialDim, Frame > &deriv_spatial_metric) noexcept
Computes the auxiliary variable used by the generalized harmonic formulation of Einstein&#39;s equations...
Conjugate momentum to the spacetime metric.
Definition: Tags.hpp:29
void trace(gsl::not_null< Scalar< DataType > *> trace, const Tensor< DataType, Symmetry< 1, 1 >, index_list< Index0, Index0 >> &tensor, const Tensor< DataType, Symmetry< 1, 1 >, index_list< change_index_up_lo< Index0 >, change_index_up_lo< Index0 >>> &metric) noexcept
Computes trace of a rank-2 symmetric tensor.
void inverse_spacetime_metric(gsl::not_null< tnsr::AA< DataType, SpatialDim, Frame > *> inverse_spacetime_metric, const Scalar< DataType > &lapse, const tnsr::I< DataType, SpatialDim, Frame > &shift, const tnsr::II< DataType, SpatialDim, Frame > &inverse_spatial_metric) noexcept
Compute inverse spacetime metric from inverse spatial metric, lapse and shift.
Definition: Tags.hpp:17
std::array< T, Dim - 1 > all_but_specified_element_of(const std::array< T, Dim > &a, const size_t element_to_remove) noexcept
Construct an array from an existing array omitting one element.
Definition: StdArrayHelpers.hpp:98
std::result_of_t< const Invocable &(const std::array< double, VolumeDim > &)> numerical_derivative(const Invocable &function, const std::array< double, VolumeDim > &x, const size_t direction, const double delta) noexcept
Calculates the derivative of an Invocable at a point x - represented by an array of doubles - in the ...
Definition: TestHelpers.hpp:286
Gauge source function for the generalized harmonic system.
Definition: Tags.hpp:125
Compute the RHS of the Generalized Harmonic formulation of Einstein&#39;s equations.
Definition: Equations.hpp:56
Defines the class Affine.
Definition: Tags.hpp:44
Defines functions to calculate the generalized harmonic constraints.
Holds the number of grid points, basis, and quadrature in each direction of the computational grid...
Definition: Mesh.hpp:50
Commonly used routines, functions and definitions shared amongst unit tests.
Define prefixes for DataBox tags.
Product of three one-dimensional CoordinateMaps.
Definition: ProductMaps.hpp:86
Definition: Tags.hpp:52
Inverse of the spatial metric.
Definition: Tags.hpp:33
Prefix indicating spatial derivatives.
Definition: PartialDerivatives.hpp:54
Defines Functions for calculating spacetime tensors from 3+1 quantities.
void trace_last_indices(gsl::not_null< Tensor< DataType, Symmetry< 1 >, index_list< Index0 >> *> trace_of_tensor, const Tensor< DataType, Symmetry< 2, 1, 1 >, index_list< Index0, Index1, Index1 >> &tensor, const Tensor< DataType, Symmetry< 1, 1 >, index_list< change_index_up_lo< Index1 >, change_index_up_lo< Index1 >>> &metric) noexcept
Computes trace of a rank 3 tensor, which is symmetric in its last two indices, tracing the symmetric ...
void spacetime_metric(gsl::not_null< tnsr::aa< DataType, Dim, Frame > *> spacetime_metric, const Scalar< DataType > &lapse, const tnsr::I< DataType, Dim, Frame > &shift, const tnsr::ii< DataType, Dim, Frame > &spatial_metric) noexcept
Computes the spacetime metric from the spatial metric, lapse, and shift.
Prefix indicating a time derivative.
Definition: Prefixes.hpp:32
Scalar< DataType > lapse(const tnsr::I< DataType, SpatialDim, Frame > &shift, const tnsr::aa< DataType, SpatialDim, Frame > &spacetime_metric) noexcept
Compute lapse from shift and spacetime metric.
#define CHECK_ITERABLE_CUSTOM_APPROX(a, b, appx)
Same as CHECK_ITERABLE_APPROX with user-defined Approx. The third argument should be of type Approx...
Definition: TestingFramework.hpp:151
void verify_time_independent_einstein_solution(const Solution &solution, const size_t grid_size_each_dimension, const std::array< double, 3 > &lower_bound, const std::array< double, 3 > &upper_bound, const double error_tolerance) noexcept
Determines if the given solution is a time-independent solution of the Einstein equations. Uses numerical derivatives to compute the solution, on a grid extending from lower_bound to upper_bound with grid_size_each_dimension points in each dimension. The right-hand side of the Einstein equations must be zero within error_tolerance
Definition: VerifyGrSolution.hpp:60
Definition: Determinant.hpp:11
Defines functions logical_coordinates and interface_logical_coordinates.
std::remove_const_t< R > make_with_value(const T &input, const ValueType &value) noexcept
Given an object of type T, create an object of type R whose elements are initialized to value...
Definition: MakeWithValue.hpp:42
auto determinant_and_inverse(const Tensor< T, Symm, tmpl::list< Index0, Index1 >> &tensor) noexcept -> std::pair< Scalar< T >, Tensor< T, Symm, tmpl::list< change_index_up_lo< Index1 >, change_index_up_lo< Index0 >>>>
Computes the determinant and inverse of a rank-2 Tensor.
Definition: DeterminantAndInverse.hpp:357
void christoffel_first_kind(gsl::not_null< tnsr::abb< DataType, SpatialDim, Frame, Index > *> christoffel, const tnsr::abb< DataType, SpatialDim, Frame, Index > &d_metric) noexcept
Computes Christoffel symbol of the first kind from derivative of metric.
Definition: Tags.hpp:26
Affine map from .
Definition: Affine.hpp:37
Defines class Variables.
Definition: Tags.hpp:48
Define simple functions for constant expressions.
tnsr::a< DataType, SpatialDim, Frame > gauge_constraint(const tnsr::a< DataType, SpatialDim, Frame > &gauge_function, const tnsr::a< DataType, SpatialDim, Frame > &spacetime_normal_one_form, const tnsr::A< DataType, SpatialDim, Frame > &spacetime_normal_vector, const tnsr::II< DataType, SpatialDim, Frame > &inverse_spatial_metric, const tnsr::AA< DataType, SpatialDim, Frame > &inverse_spacetime_metric, const tnsr::aa< DataType, SpatialDim, Frame > &pi, const tnsr::iaa< DataType, SpatialDim, Frame > &phi) noexcept
Computes the generalized-harmonic gauge constraint.
Definition: Constraints.cpp:953
Defines the class template Mesh.
void pi(gsl::not_null< tnsr::aa< DataType, SpatialDim, Frame > *> pi, const Scalar< DataType > &lapse, const Scalar< DataType > &dt_lapse, const tnsr::I< DataType, SpatialDim, Frame > &shift, const tnsr::I< DataType, SpatialDim, Frame > &dt_shift, const tnsr::ii< DataType, SpatialDim, Frame > &spatial_metric, const tnsr::ii< DataType, SpatialDim, Frame > &dt_spatial_metric, const tnsr::iaa< DataType, SpatialDim, Frame > &phi) noexcept
Computes the conjugate momentum of the spacetime metric .
Defines class CoordinateMap.
Defines classes for Tensor.
tnsr::I< DataVector, VolumeDim, Frame::Logical > logical_coordinates(const Mesh< VolumeDim > &mesh) noexcept
Compute the logical coordinates in an Element.
Definition: LogicalCoordinates.cpp:20
void raise_or_lower_first_index(gsl::not_null< Tensor< DataType, Symmetry< 2, 1, 1 >, index_list< change_index_up_lo< Index0 >, Index1, Index1 >> *> result, const Tensor< DataType, Symmetry< 2, 1, 1 >, index_list< Index0, Index1, Index1 >> &tensor, const Tensor< DataType, Symmetry< 1, 1 >, index_list< change_index_up_lo< Index0 >, change_index_up_lo< Index0 >>> &metric) noexcept
Raises or lowers the first index of a rank 3 tensor which is symmetric in the last two indices...
tnsr::I< DataType, SpatialDim, Frame > shift(const tnsr::aa< DataType, SpatialDim, Frame > &spacetime_metric, const tnsr::II< DataType, SpatialDim, Frame > &inverse_spatial_metric) noexcept
Compute shift from spacetime metric and inverse spatial metric.
#define CHECK_ITERABLE_APPROX(a, b)
A wrapper around Catch&#39;s CHECK macro that checks approximate equality of entries in iterable containe...
Definition: TestingFramework.hpp:139
Wraps the template metaprogramming library used (brigand)
Defines the class templates ProductOf2Maps and ProductOf3Maps.
Defines functions and classes from the GSL.
gsl::not_null< T * > make_not_null(T *ptr) noexcept
Construct a not_null from a pointer. Often this will be done as an implicit conversion, but it may be necessary to perform the conversion explicitly when type deduction is desired.
Definition: Gsl.hpp:879
Code to wrap or improve the Catch testing framework used for unit tests.
void gauge_source(gsl::not_null< tnsr::a< DataType, SpatialDim, Frame > *> gauge_source_h, const Scalar< DataType > &lapse, const Scalar< DataType > &dt_lapse, const tnsr::i< DataType, SpatialDim, Frame > &deriv_lapse, const tnsr::I< DataType, SpatialDim, Frame > &shift, const tnsr::I< DataType, SpatialDim, Frame > &dt_shift, const tnsr::iJ< DataType, SpatialDim, Frame > &deriv_shift, const tnsr::ii< DataType, SpatialDim, Frame > &spatial_metric, const Scalar< DataType > &trace_extrinsic_curvature, const tnsr::i< DataType, SpatialDim, Frame > &trace_christoffel_last_indices) noexcept
Computes generalized harmonic gauge source function.
Defines class template GeneralizedHarmonicEquations.
Definition: IndexType.hpp:44
tnsr::A< DataType, SpatialDim, Frame > spacetime_normal_vector(const Scalar< DataType > &lapse, const tnsr::I< DataType, SpatialDim, Frame > &shift) noexcept
Computes spacetime normal vector from lapse and shift.
Defines classes SimpleTag, PrefixTag, ComputeTag and several functions for retrieving tag info...
Defines Functions for calculating spacetime tensors from 3+1 quantities.
Defines arithmetic operators for std::array and other helpful functions.
Defines functions to calculate Christoffel symbols.
void verify_consistency(const Solution &solution, const double time, const tnsr::I< double, 3 > &position, const double derivative_delta, const double derivative_tolerance) noexcept
Check the consistency of dependent quantities returned by a solution. This includes checking pointwis...
Definition: VerifyGrSolution.hpp:303
Defines make_with_value.
Definition: Tags.hpp:121