Line data Source code
1 1 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : /// \file 5 : /// Defines ScalarWave::Solutions::RegularSphericalWave 6 : 7 : #pragma once 8 : 9 : #include <cstddef> 10 : #include <memory> 11 : 12 : #include "DataStructures/Tensor/TypeAliases.hpp" 13 : #include "Options/String.hpp" 14 : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp" 15 : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp" 16 : #include "PointwiseFunctions/MathFunctions/MathFunction.hpp" 17 : #include "Utilities/Serialization/CharmPupable.hpp" 18 : #include "Utilities/TMPL.hpp" 19 : #include "Utilities/TaggedTuple.hpp" 20 : 21 : /// \cond 22 : class DataVector; 23 : namespace ScalarWave::Tags { 24 : struct Pi; 25 : struct Psi; 26 : template <size_t Dim> 27 : struct Phi; 28 : } // namespace ScalarWave::Tags 29 : namespace Tags { 30 : template <typename Tag> 31 : struct dt; 32 : } // namespace Tags 33 : template <size_t VolumeDim, typename Fr> 34 : class MathFunction; 35 : namespace PUP { 36 : class er; 37 : } // namespace PUP 38 : /// \endcond 39 : 40 : namespace ScalarWave::Solutions { 41 : /*! 42 : * \brief A 3D spherical wave solution to the Euclidean wave equation that is 43 : * regular at the origin 44 : * 45 : * The solution is given by \f$\Psi(\vec{x},t) = \Psi(r,t) = 46 : * \frac{F(r-t)-F(-r-t)}{r}\f$ describing an outgoing and an ingoing wave 47 : * with profile \f$F(u)\f$. For small \f$r\f$ the solution is approximated by 48 : * its Taylor expansion \f$\Psi(r,t)=2 F^\prime(-t) + \mathcal{O}(r^2)\f$. The 49 : * outgoing and ingoing waves meet at the origin (and cancel each other) when 50 : * \f$F^\prime(-t)=0\f$. 51 : * 52 : * The expansion is employed where \f$r\f$ lies within the cubic root of the 53 : * machine epsilon. Inside this radius we expect the error due to the truncation 54 : * of the Taylor expansion to be smaller than the numerical error made when 55 : * evaluating the full \f$\Psi(r,t)\f$. This is because the truncation error 56 : * scales as \f$r^2\f$ (since we keep the zeroth order, and the linear order 57 : * vanishes as all odd orders do) and the numerical error scales as 58 : * \f$\frac{\epsilon}{r}\f$, so they are comparable at 59 : * \f$r\propto\epsilon^\frac{1}{3}\f$. 60 : * 61 : * \requires the profile \f$F(u)\f$ to have a length scale of order unity so 62 : * that "small" \f$r\f$ means \f$r\ll 1\f$. This is without loss of generality 63 : * because of the scale invariance of the wave equation. The profile could be a 64 : * Gausssian centered at 0 with width 1, for instance. 65 : */ 66 1 : class RegularSphericalWave : public evolution::initial_data::InitialData, 67 : public MarkAsAnalyticSolution { 68 : public: 69 0 : static constexpr size_t volume_dim = 3; 70 0 : struct Profile { 71 0 : using type = std::unique_ptr<MathFunction<1, Frame::Inertial>>; 72 0 : static constexpr Options::String help = { 73 : "The radial profile of the spherical wave."}; 74 : }; 75 : 76 0 : using options = tmpl::list<Profile>; 77 : 78 0 : static constexpr Options::String help = { 79 : "A spherical wave solution of the Euclidean wave equation that is " 80 : "regular at the origin"}; 81 : 82 0 : using tags = 83 : tmpl::list<Tags::Psi, Tags::Pi, Tags::Phi<3>, ::Tags::dt<Tags::Psi>, 84 : ::Tags::dt<Tags::Pi>, ::Tags::dt<Tags::Phi<3>>>; 85 : 86 0 : RegularSphericalWave() = default; 87 0 : explicit RegularSphericalWave( 88 : std::unique_ptr<MathFunction<1, Frame::Inertial>> profile); 89 0 : RegularSphericalWave(const RegularSphericalWave& other); 90 0 : RegularSphericalWave& operator=(const RegularSphericalWave& other); 91 0 : RegularSphericalWave(RegularSphericalWave&&) = default; 92 0 : RegularSphericalWave& operator=(RegularSphericalWave&&) = default; 93 0 : ~RegularSphericalWave() override = default; 94 : 95 0 : auto get_clone() const 96 : -> std::unique_ptr<evolution::initial_data::InitialData> override; 97 : 98 : /// \cond 99 : explicit RegularSphericalWave(CkMigrateMessage* msg); 100 : using PUP::able::register_constructor; 101 : WRAPPED_PUPable_decl_template(RegularSphericalWave); 102 : /// \endcond 103 : 104 0 : tuples::TaggedTuple<Tags::Psi, Tags::Pi, Tags::Phi<3>> variables( 105 : const tnsr::I<DataVector, 3>& x, double t, 106 : tmpl::list<Tags::Psi, Tags::Pi, Tags::Phi<3>> /*meta*/) const; 107 : 108 : tuples::TaggedTuple<::Tags::dt<Tags::Psi>, ::Tags::dt<Tags::Pi>, 109 : ::Tags::dt<Tags::Phi<3>>> 110 0 : variables(const tnsr::I<DataVector, 3>& x, double t, 111 : tmpl::list<::Tags::dt<Tags::Psi>, ::Tags::dt<Tags::Pi>, 112 : ::Tags::dt<Tags::Phi<3>>> /*meta*/) const; 113 : 114 : // NOLINTNEXTLINE(google-runtime-references) 115 0 : void pup(PUP::er& p) override; 116 : 117 : private: 118 : // NOLINTNEXTLINE(readability-redundant-declaration) 119 0 : friend bool operator==(const RegularSphericalWave& lhs, 120 : const RegularSphericalWave& rhs); 121 : // NOLINTNEXTLINE(readability-redundant-declaration) 122 0 : friend bool operator!=(const RegularSphericalWave& lhs, 123 : const RegularSphericalWave& rhs); 124 0 : std::unique_ptr<MathFunction<1, Frame::Inertial>> profile_; 125 : }; 126 : } // namespace ScalarWave::Solutions