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