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/TaggedTuple.hpp"
13 : #include "DataStructures/Tensor/TypeAliases.hpp"
14 : #include "Options/String.hpp"
15 : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp"
16 : #include "PointwiseFunctions/InitialDataUtilities/InitialData.hpp"
17 : #include "PointwiseFunctions/MathFunctions/MathFunction.hpp"
18 : #include "Utilities/Serialization/CharmPupable.hpp"
19 : #include "Utilities/TMPL.hpp"
20 :
21 : /// \cond
22 : class DataVector;
23 : namespace ScalarWave::Tags {
24 : struct Pi;
25 : struct Psi;
26 : template <size_t Dim, typename Frame>
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 = tmpl::list<Tags::Psi, Tags::Pi, Tags::Phi<3, Frame::Inertial>,
83 : ::Tags::dt<Tags::Psi>, ::Tags::dt<Tags::Pi>,
84 : ::Tags::dt<Tags::Phi<3, Frame::Inertial>>>;
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 : tuples::TaggedTuple<Tags::Psi, Tags::Pi, Tags::Phi<3, Frame::Inertial>>
105 0 : variables(const tnsr::I<DataVector, 3>& x, double t,
106 : tmpl::list<Tags::Psi, Tags::Pi,
107 : Tags::Phi<3, Frame::Inertial>> /*meta*/) const;
108 :
109 : tuples::TaggedTuple<::Tags::dt<Tags::Psi>, ::Tags::dt<Tags::Pi>,
110 : ::Tags::dt<Tags::Phi<3, Frame::Inertial>>>
111 0 : variables(
112 : const tnsr::I<DataVector, 3>& x, double t,
113 : tmpl::list<::Tags::dt<Tags::Psi>, ::Tags::dt<Tags::Pi>,
114 : ::Tags::dt<Tags::Phi<3, Frame::Inertial>>> /*meta*/) const;
115 :
116 : // NOLINTNEXTLINE(google-runtime-references)
117 0 : void pup(PUP::er& p) override;
118 :
119 : private:
120 : // NOLINTNEXTLINE(readability-redundant-declaration)
121 0 : friend bool operator==(const RegularSphericalWave& lhs,
122 : const RegularSphericalWave& rhs);
123 : // NOLINTNEXTLINE(readability-redundant-declaration)
124 0 : friend bool operator!=(const RegularSphericalWave& lhs,
125 : const RegularSphericalWave& rhs);
126 0 : std::unique_ptr<MathFunction<1, Frame::Inertial>> profile_;
127 : };
128 : } // namespace ScalarWave::Solutions
|