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 :
8 : #include "DataStructures/DataBox/Protocols/Mutator.hpp"
9 : #include "DataStructures/DataVector.hpp"
10 : #include "DataStructures/Tensor/Tensor.hpp"
11 : #include "Domain/Tags.hpp"
12 : #include "Evolution/Initialization/InitialData.hpp"
13 : #include "Evolution/Initialization/Tags.hpp"
14 : #include "Evolution/Systems/CurvedScalarWave/BackgroundSpacetime.hpp"
15 : #include "Evolution/Systems/CurvedScalarWave/System.hpp"
16 : #include "Evolution/Systems/ScalarWave/System.hpp"
17 : #include "Evolution/Systems/ScalarWave/TagsDeclarations.hpp"
18 : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
19 : #include "PointwiseFunctions/AnalyticData/Tags.hpp"
20 : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
21 : #include "PointwiseFunctions/InitialDataUtilities/Tags/InitialData.hpp"
22 : #include "Utilities/CallWithDynamicType.hpp"
23 : #include "Utilities/ProtocolHelpers.hpp"
24 : #include "Utilities/TMPL.hpp"
25 :
26 : /// \cond
27 : namespace Tags {
28 : struct Time;
29 : } // namespace Tags
30 : /// \endcond
31 :
32 : /// \brief Utilities for initializing the curved scalar wave system.
33 1 : namespace CurvedScalarWave::Initialization {
34 : /// \ingroup InitializationGroup
35 : /// \brief Mutator meant to be used with
36 : /// `Initialization::Actions::AddSimpleTags` to initialize the constraint
37 : /// damping parameters of the CurvedScalarWave system
38 : ///
39 : /// DataBox changes:
40 : /// - Adds:
41 : /// * `CurvedScalarWave::Tags::ConstraintGamma1`
42 : /// * `CurvedScalarWave::Tags::ConstraintGamma2`
43 : /// - Removes: nothing
44 : /// - Modifies: nothing
45 :
46 : template <size_t Dim>
47 1 : struct InitializeConstraintDampingGammas
48 : : tt::ConformsTo<db::protocols::Mutator> {
49 0 : using return_tags =
50 : tmpl::list<Tags::ConstraintGamma1, Tags::ConstraintGamma2>;
51 0 : using argument_tags = tmpl::list<domain::Tags::Mesh<Dim>>;
52 :
53 0 : static void apply(const gsl::not_null<Scalar<DataVector>*> gamma1,
54 : const gsl::not_null<Scalar<DataVector>*> gamma2,
55 : const Mesh<Dim>& mesh) {
56 : const size_t number_of_grid_points = mesh.number_of_grid_points();
57 : *gamma1 = Scalar<DataVector>{number_of_grid_points, 0.};
58 : *gamma2 = Scalar<DataVector>{number_of_grid_points, 1.};
59 : }
60 : };
61 :
62 : /*!
63 : * \brief Analytic initial data for scalar waves in curved spacetime
64 : *
65 : * \details When evolving a scalar field propagating through curved spacetime,
66 : * this mutator initializes the scalar field and spacetime variables using
67 : *
68 : * 1. analytic solution(s) or data of the flat or curved scalar wave equation
69 : * for the evolution variables
70 : * 2. solutions of the Einstein equations for the spacetime background.
71 : *
72 : * If the scalar field initial data returns `CurvedScalarWave` tags, \f$\Psi\f$,
73 : * \f$\Pi\f$ and \f$\Phi_i\f$ will simply be forwarded from the initial data
74 : * class. Alternatively, the scalar field initial data can be provided using any
75 : * member class of `ScalarWave::Solutions` which return `ScalarWave` tags. In
76 : * this case, \f$\Phi_i\f$ and \f$\Psi\f$ will also be forwarded but
77 : * \f$\Pi\f$ will be adjusted to account for the curved background. Its
78 : * definition comes from requiring it to be the future-directed time derivative
79 : * of the scalar field in curved spacetime:
80 : *
81 : * \f{align}
82 : * \Pi :=& -n^a \partial_a \Psi \\
83 : * =& \frac{1}{\alpha}\left(\beta^k \Phi_k - {\partial_t\Psi}\right),\\
84 : * =& \frac{1}{\alpha}\left(\beta^k \Phi_k + {\Pi}_{\mathrm{flat}}\right),
85 : * \f}
86 : *
87 : * where \f$n^a\f$ is the unit normal to spatial slices of the spacetime
88 : * foliation, and \f${\Pi}_{\mathrm{flat}}\f$ comes from the flat spacetime
89 : * solution.
90 : *
91 : * DataBox changes:
92 : * - Adds: nothing
93 : * - Removes: nothing
94 : * - Modifies: Tags::Variables<tmpl::list<CurvedScalarWave::Tags::Psi,
95 : * CurvedScalarWave::Tags::Pi, CurvedScalarWave::Tags::Phi<Dim>>>
96 : */
97 : template <size_t Dim, typename DerivedClasses>
98 1 : struct InitializeEvolvedVariables : tt::ConformsTo<db::protocols::Mutator> {
99 0 : using flat_variables_tag = typename ScalarWave::System<Dim>::variables_tag;
100 0 : using curved_variables_tag =
101 : typename CurvedScalarWave::System<Dim>::variables_tag;
102 :
103 0 : using return_tags = tmpl::list<curved_variables_tag>;
104 0 : using argument_tags =
105 : tmpl::list<::Tags::Time, domain::Tags::Coordinates<Dim, Frame::Inertial>,
106 : evolution::initial_data::Tags::InitialData,
107 : gr::Tags::Lapse<DataVector>, gr::Tags::Shift<DataVector, Dim>>;
108 :
109 0 : static void apply(
110 : const gsl::not_null<typename curved_variables_tag::type*> evolved_vars,
111 : const double initial_time,
112 : const tnsr::I<DataVector, Dim>& inertial_coords,
113 : const evolution::initial_data::InitialData& solution_or_data,
114 : [[maybe_unused]] const Scalar<DataVector>& lapse,
115 : [[maybe_unused]] const tnsr::I<DataVector, Dim>& shift) {
116 : call_with_dynamic_type<void, DerivedClasses>(
117 : &solution_or_data,
118 : [&evolved_vars, initial_time, &inertial_coords, &lapse,
119 : &shift]<typename InitialDataSubclass>(
120 : const InitialDataSubclass* const data_or_solution) {
121 : if constexpr (is_analytic_data_v<InitialDataSubclass> or
122 : is_analytic_solution_v<InitialDataSubclass>) {
123 : if constexpr (tmpl::list_contains_v<
124 : typename InitialDataSubclass::tags,
125 : CurvedScalarWave::Tags::Psi>) {
126 : (void)lapse, (void)shift;
127 : evolved_vars->assign_subset(
128 : evolution::Initialization::initial_data(
129 : *data_or_solution, inertial_coords, initial_time,
130 : typename curved_variables_tag::tags_list{}));
131 : } else {
132 : static_assert(
133 : tmpl::list_contains_v<typename InitialDataSubclass::tags,
134 : ScalarWave::Tags::Psi>,
135 : "The initial data class must either calculate ScalarWave "
136 : "or CurvedScalarWave variables.");
137 : const auto initial_data = evolution::Initialization::initial_data(
138 : *data_or_solution, inertial_coords, initial_time,
139 : typename flat_variables_tag::tags_list{});
140 :
141 : get<CurvedScalarWave::Tags::Psi>(*evolved_vars) =
142 : get<ScalarWave::Tags::Psi>(initial_data);
143 : get<CurvedScalarWave::Tags::Phi<Dim>>(*evolved_vars) =
144 : get<ScalarWave::Tags::Phi<Dim>>(initial_data);
145 : const auto shift_dot_dpsi = dot_product(
146 : shift, get<ScalarWave::Tags::Phi<Dim>>(initial_data));
147 : get(get<CurvedScalarWave::Tags::Pi>(*evolved_vars)) =
148 : (get(shift_dot_dpsi) +
149 : get(get<ScalarWave::Tags::Pi>(initial_data))) /
150 : get(lapse);
151 : }
152 : } else {
153 : ERROR(
154 : "Trying to use "
155 : "'evolution::Initialization::Actions::SetVariables' with a "
156 : "class that's not marked as analytic solution or analytic "
157 : "data. To support numeric initial data, add a "
158 : "system-specific initialization routine to your executable.");
159 : }
160 : });
161 : }
162 : };
163 : } // namespace CurvedScalarWave::Initialization
|