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