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