Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <memory>
8 : #include <pup.h>
9 : #include <string>
10 : #include <type_traits>
11 :
12 : #include "DataStructures/DataVector.hpp"
13 : #include "DataStructures/TaggedTuple.hpp"
14 : #include "DataStructures/Tensor/Tensor.hpp"
15 : #include "Evolution/Systems/GeneralizedHarmonic/GaugeSourceFunctions/Gauges.hpp"
16 : #include "Evolution/Systems/GeneralizedHarmonic/Tags.hpp"
17 : #include "Options/String.hpp"
18 : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp"
19 : #include "PointwiseFunctions/GeneralRelativity/Tags.hpp"
20 : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
21 : #include "Utilities/CallWithDynamicType.hpp"
22 : #include "Utilities/ErrorHandling/Assert.hpp"
23 : #include "Utilities/Gsl.hpp"
24 : #include "Utilities/TMPL.hpp"
25 :
26 : /// \cond
27 : template <size_t Dim>
28 : class Mesh;
29 : /// \endcond
30 :
31 1 : namespace gh::gauges {
32 : /*!
33 : * \brief Imposes the analytic gauge condition,
34 : * \f$H_a=\Gamma_a^{\mathrm{analytic}}\f$ from an analytic solution or analytic
35 : * data.
36 : *
37 : * \warning Assumes \f$\partial_t \Gamma_a=0\f$ i.e. the solution is static or
38 : * in harmonic gauge.
39 : */
40 1 : class AnalyticChristoffel final : public GaugeCondition {
41 : private:
42 : template <size_t SpatialDim>
43 0 : using solution_tags =
44 : tmpl::list<gh::Tags::Pi<DataVector, SpatialDim>,
45 : gh::Tags::Phi<DataVector, SpatialDim>,
46 : gr::Tags::SpacetimeMetric<DataVector, SpatialDim>,
47 : gr::Tags::Lapse<DataVector>,
48 : gr::Tags::Shift<DataVector, SpatialDim>,
49 : gr::Tags::SpatialMetric<DataVector, SpatialDim>>;
50 :
51 : public:
52 : /// \brief What analytic solution/data to prescribe.
53 1 : struct AnalyticPrescription {
54 0 : static constexpr Options::String help =
55 : "What analytic solution/data to prescribe.";
56 0 : using type = std::unique_ptr<evolution::initial_data::InitialData>;
57 : };
58 :
59 0 : using options = tmpl::list<AnalyticPrescription>;
60 :
61 0 : static constexpr Options::String help{
62 : "Apply the analytic gauge condition H_a = Gamma_a, where Gamma_a comes "
63 : "from the AnalyticPrescription."};
64 :
65 0 : AnalyticChristoffel() = default;
66 0 : AnalyticChristoffel(const AnalyticChristoffel&);
67 0 : AnalyticChristoffel& operator=(const AnalyticChristoffel&);
68 0 : AnalyticChristoffel(AnalyticChristoffel&&) = default;
69 0 : AnalyticChristoffel& operator=(AnalyticChristoffel&&) = default;
70 0 : ~AnalyticChristoffel() override = default;
71 :
72 0 : explicit AnalyticChristoffel(
73 : std::unique_ptr<evolution::initial_data::InitialData>
74 : analytic_prescription);
75 :
76 : /// \cond
77 : explicit AnalyticChristoffel(CkMigrateMessage* msg);
78 : using PUP::able::register_constructor;
79 : WRAPPED_PUPable_decl_template(AnalyticChristoffel); // NOLINT
80 : /// \endcond
81 :
82 : template <size_t SpatialDim, class AllSolutionsForChristoffelAnalytic>
83 0 : void gauge_and_spacetime_derivative(
84 : const gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame::Inertial>*>
85 : gauge_h,
86 : const gsl::not_null<tnsr::ab<DataVector, SpatialDim, Frame::Inertial>*>
87 : d4_gauge_h,
88 : const Mesh<SpatialDim>& mesh, const double time,
89 : const tnsr::I<DataVector, SpatialDim, Frame::Inertial>& inertial_coords,
90 : const InverseJacobian<DataVector, SpatialDim, Frame::ElementLogical,
91 : Frame::Inertial>& inverse_jacobian,
92 : const AllSolutionsForChristoffelAnalytic /*meta*/) const {
93 : // Use .get() to avoid Clang-13 bug: with -Og in C++20 mode, the compiler
94 : // rewrites unique_ptr != nullptr via std::operator== but fails to emit the
95 : // out-of-line instantiation, causing a linker error.
96 : ASSERT(analytic_prescription_.get() != nullptr,
97 : "The analytic prescription cannot be nullptr.");
98 : const auto solution_vars = call_with_dynamic_type<
99 : tuples::tagged_tuple_from_typelist<solution_tags<SpatialDim>>,
100 : AllSolutionsForChristoffelAnalytic>(
101 : analytic_prescription_.get(),
102 : [&inertial_coords, &time](const auto* const analytic_solution_or_data) {
103 : if constexpr (is_analytic_solution_v<std::decay_t<
104 : decltype(*analytic_solution_or_data)>>) {
105 : return analytic_solution_or_data->variables(
106 : inertial_coords, time, solution_tags<SpatialDim>{});
107 :
108 : } else {
109 : (void)time;
110 : return analytic_solution_or_data->variables(
111 : inertial_coords, solution_tags<SpatialDim>{});
112 : }
113 : });
114 : gauge_and_spacetime_derivative_impl(gauge_h, d4_gauge_h, mesh,
115 : inverse_jacobian, solution_vars);
116 : }
117 :
118 : // NOLINTNEXTLINE(google-runtime-references)
119 0 : void pup(PUP::er& p) override;
120 :
121 0 : std::unique_ptr<GaugeCondition> get_clone() const override;
122 :
123 : private:
124 : template <size_t SpatialDim>
125 0 : void gauge_and_spacetime_derivative_impl(
126 : gsl::not_null<tnsr::a<DataVector, SpatialDim, Frame::Inertial>*> gauge_h,
127 : gsl::not_null<tnsr::ab<DataVector, SpatialDim, Frame::Inertial>*>
128 : d4_gauge_h,
129 : const Mesh<SpatialDim>& mesh,
130 : const InverseJacobian<DataVector, SpatialDim, Frame::ElementLogical,
131 : Frame::Inertial>& inverse_jacobian,
132 : const tuples::tagged_tuple_from_typelist<solution_tags<SpatialDim>>&
133 : solution_vars) const;
134 :
135 0 : std::unique_ptr<evolution::initial_data::InitialData> analytic_prescription_;
136 : };
137 : } // namespace gh::gauges
|