CheckBurgersSolution.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 #include <vector>
11 
12 #include "DataStructures/DataVector.hpp"
14 #include "Evolution/Systems/Burgers/Fluxes.hpp"
15 #include "Evolution/TypeTraits.hpp"
17 #include "Utilities/TMPL.hpp"
18 
19 /// \cond
20 namespace Burgers {
21 namespace Tags {
22 struct U;
23 } // namespace Tags
24 } // namespace Burgers
25 namespace Tags {
26 template <typename Tag>
27 struct dt;
28 } // namespace Tags
29 /// \endcond
30 
31 template <typename Solution>
32 void check_burgers_solution(const Solution& solution,
33  const DataVector& positions,
34  const std::vector<double>& times) noexcept {
35  static_assert(evolution::is_analytic_solution_v<Solution>,
36  "Solution was not derived from AnalyticSolution");
37  // Check that different functions are consistent.
38  const tnsr::I<DataVector, 1> positions_tnsr{{{positions}}};
39  for (const double time : times) {
40  const auto value = solution.u(positions_tnsr, time);
41  const auto time_deriv = solution.du_dt(positions_tnsr, time);
42  CHECK(get<Burgers::Tags::U>(solution.variables(
43  positions_tnsr, time, tmpl::list<Burgers::Tags::U>{})) == value);
44  CHECK(get<Tags::dt<Burgers::Tags::U>>(solution.variables(
45  positions_tnsr, time,
46  tmpl::list<Tags::dt<Burgers::Tags::U>>{})) ==
47  time_deriv);
48  for (size_t point = 0; point < positions.size(); ++point) {
49  const tnsr::I<double, 1> xp{{{positions[point]}}};
50  const double up = get(value)[point];
51  const double dtup = get(time_deriv)[point];
52  CHECK(get(solution.u(xp, time)) == approx(up));
53  CHECK(get(solution.du_dt(xp, time)) == approx(dtup));
54  // Check that the time derivative is the derivative of the
55  // value.
57  [&solution, &xp](const std::array<double, 1>& t) noexcept {
58  return std::array<double, 1>{{get(solution.u(xp, t[0]))}};
59  },
60  std::array<double, 1>{{time}}, 0, 1e-4)[0] ==
61  approx.epsilon(1e-10)(dtup));
62  // Check that the Burgers equation is satisfied.
63  CHECK(numerical_derivative([&solution, &time](
64  const std::array<double, 1>& x) noexcept {
65  tnsr::I<DataVector, 1> flux{{{DataVector(1)}}};
66  Burgers::Fluxes::apply(
67  &flux, solution.u(tnsr::I<DataVector, 1>{{{{x[0]}}}}, time));
68  return std::array<double, 1>{{get<0>(flux)[0]}};
69  },
70  std::array<double, 1>{{get<0>(xp)}}, 0,
71  1e-4)[0] == approx(-dtup));
72  }
73  }
74 }
get
constexpr Tag::type & get(Variables< TagList > &v) noexcept
Return Tag::type pointing into the contiguous array.
Definition: Variables.hpp:638
vector
TestingFramework.hpp
Burgers
Items related to evolving the Burgers equation .
Definition: EvolveBurgersFwd.hpp:6
TestHelpers.hpp
numerical_derivative
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
cstddef
array
DataVector
Stores a collection of function values.
Definition: DataVector.hpp:42
Tags::dt
Prefix indicating a time derivative.
Definition: Prefixes.hpp:29
Tensor.hpp
std::time
T time(T... args)
TMPL.hpp