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 <string>
8 : #include <vector>
9 :
10 : #include "DataStructures/ComplexDataVector.hpp"
11 : #include "DataStructures/DataVector.hpp"
12 : #include "DataStructures/Tensor/TypeAliases.hpp"
13 : #include "Domain/Tags.hpp"
14 : #include "Elliptic/BoundaryConditions/BoundaryCondition.hpp"
15 : #include "Elliptic/BoundaryConditions/BoundaryConditionType.hpp"
16 : #include "Elliptic/Systems/SelfForce/Scalar/Tags.hpp"
17 : #include "Options/String.hpp"
18 : #include "Utilities/Gsl.hpp"
19 : #include "Utilities/TMPL.hpp"
20 :
21 : namespace ScalarSelfForce::BoundaryConditions {
22 :
23 : /*!
24 : * \brief Radial Sommerfeld boundary conditions for the m-mode field.
25 : *
26 : * The radial boundary conditions are given in Eq. (4.10-4.11) in
27 : * \cite Osburn:2022bby . They apply both near the Kerr horizon (inner radial
28 : * boundary) and at large distance (outer radial boundary):
29 : *
30 : * \begin{equation}
31 : * n_i F^i = i m \Omega \Psi_m
32 : * \end{equation}
33 : *
34 : * These boundary conditions currently assume a circular equatorial orbit.
35 : */
36 1 : class Sommerfeld : public elliptic::BoundaryConditions::BoundaryCondition<2> {
37 : private:
38 0 : using Base = elliptic::BoundaryConditions::BoundaryCondition<2>;
39 :
40 : public:
41 0 : struct BlackHoleMass {
42 0 : static constexpr Options::String help =
43 : "Kerr mass parameter 'M' of the black hole";
44 0 : using type = double;
45 : };
46 0 : struct BlackHoleSpin {
47 0 : static constexpr Options::String help =
48 : "Kerr dimensionless spin parameter 'chi' of the black hole";
49 0 : using type = double;
50 : };
51 0 : struct OrbitalRadius {
52 0 : static constexpr Options::String help =
53 : "Radius 'r_0' of the circular orbit";
54 0 : using type = double;
55 : };
56 0 : struct MModeNumber {
57 0 : static constexpr Options::String help =
58 : "Mode number 'm' of the scalar field";
59 0 : using type = int;
60 : };
61 0 : struct HyperboloidalSlicing {
62 0 : static constexpr Options::String help =
63 : "Whether hyperboloidal slicing is applied. If true, a simple Neumann "
64 : "boundary condition is applied.";
65 0 : using type = bool;
66 : };
67 0 : struct Order {
68 0 : static constexpr Options::String help =
69 : "Order of the boundary condition. First order (Order=1) implements "
70 : "just the leading 'i m Omega' term. Second order (Order=2) includes "
71 : "the next-to-leading '1/r' term as well (Robin-type).";
72 0 : using type = int;
73 : };
74 :
75 0 : static constexpr Options::String help =
76 : "Radial Sommerfeld boundary condition";
77 0 : using options = tmpl::list<BlackHoleMass, BlackHoleSpin, OrbitalRadius,
78 : MModeNumber, HyperboloidalSlicing, Order>;
79 :
80 0 : Sommerfeld() = default;
81 0 : Sommerfeld(const Sommerfeld&) = default;
82 0 : Sommerfeld& operator=(const Sommerfeld&) = default;
83 0 : Sommerfeld(Sommerfeld&&) = default;
84 0 : Sommerfeld& operator=(Sommerfeld&&) = default;
85 0 : ~Sommerfeld() override = default;
86 :
87 0 : explicit Sommerfeld(double black_hole_mass, double black_hole_spin,
88 : double orbital_radius, int m_mode_number,
89 : bool hyperboloidal_slicing, int order);
90 :
91 0 : double black_hole_mass() const { return black_hole_mass_; }
92 0 : double black_hole_spin() const { return black_hole_spin_; }
93 0 : double orbital_radius() const { return orbital_radius_; }
94 0 : int m_mode_number() const { return m_mode_number_; }
95 0 : bool hyperboloidal_slicing() const { return hyperboloidal_slicing_; }
96 0 : int order() const { return order_; }
97 :
98 : /// \cond
99 : explicit Sommerfeld(CkMigrateMessage* m);
100 : using PUP::able::register_constructor;
101 : WRAPPED_PUPable_decl_template(Sommerfeld);
102 : /// \endcond
103 :
104 0 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition> get_clone()
105 : const override;
106 :
107 0 : std::vector<elliptic::BoundaryConditionType> boundary_condition_types()
108 : const override {
109 : return {elliptic::BoundaryConditionType::Neumann};
110 : }
111 :
112 0 : using argument_tags =
113 : tmpl::list<Tags::Alpha, Tags::Beta, Tags::Gamma>;
114 0 : using volume_tags = tmpl::list<>;
115 :
116 0 : void apply(gsl::not_null<Scalar<ComplexDataVector>*> field,
117 : gsl::not_null<Scalar<ComplexDataVector>*> n_dot_flux,
118 : const tnsr::i<ComplexDataVector, 2>& deriv_field,
119 : const tnsr::I<ComplexDataVector, 2>& alpha,
120 : const Scalar<ComplexDataVector>& beta,
121 : const tnsr::i<ComplexDataVector, 2>& gamma) const;
122 :
123 0 : using argument_tags_linearized =
124 : tmpl::list<Tags::Alpha, Tags::Beta, Tags::Gamma>;
125 0 : using volume_tags_linearized = tmpl::list<>;
126 :
127 0 : void apply_linearized(
128 : gsl::not_null<Scalar<ComplexDataVector>*> field_correction,
129 : gsl::not_null<Scalar<ComplexDataVector>*> n_dot_flux_correction,
130 : const tnsr::i<ComplexDataVector, 2>& deriv_field_correction,
131 : const tnsr::I<ComplexDataVector, 2>& alpha,
132 : const Scalar<ComplexDataVector>& beta,
133 : const tnsr::i<ComplexDataVector, 2>& gamma) const;
134 :
135 : // NOLINTNEXTLINE
136 0 : void pup(PUP::er& p) override;
137 :
138 : private:
139 0 : friend bool operator==(const Sommerfeld& lhs, const Sommerfeld& rhs);
140 :
141 0 : double black_hole_mass_{std::numeric_limits<double>::signaling_NaN()};
142 0 : double black_hole_spin_{std::numeric_limits<double>::signaling_NaN()};
143 0 : double orbital_radius_{std::numeric_limits<double>::signaling_NaN()};
144 0 : int m_mode_number_{};
145 0 : bool hyperboloidal_slicing_{};
146 0 : int order_{};
147 : };
148 :
149 0 : bool operator!=(const Sommerfeld& lhs, const Sommerfeld& rhs);
150 :
151 : } // namespace ScalarSelfForce::BoundaryConditions
|