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 "Options/String.hpp" 17 : #include "Utilities/Gsl.hpp" 18 : #include "Utilities/TMPL.hpp" 19 : 20 0 : namespace GrSelfForce::BoundaryConditions { 21 : 22 : /*! 23 : * \brief Angular boundary conditions for the m-mode metric perturbations. 24 : * 25 : * The angular boundary conditions are determined by enforcing regularity of 26 : * the metric perturbation at the poles $\theta=0,\pi$: 27 : * \begin{align} 28 : * &\Psi_{m=1}^{0,1,4,7,8,9} = 0 \\ 29 : * &\partial_\theta \Psi_{m=1}^{2,3,5,6} = 0 \\ 30 : * &\Psi_{m=2}^{0,1,2,3,4,5,6} = 0 \\ 31 : * &\partial_\theta \Psi_{m=2}^{7,8,9} = 0 \\ 32 : * &\Psi_{m>2} = 0 \\ 33 : * \end{align} 34 : * The ordering of components in $\Psi$ here is: 35 : * $\{tt,tr,t\theta,t\phi,rr,r\theta,r\phi,\theta\theta,\theta\phi,\phi\phi\}$. 36 : */ 37 1 : class Angular : public elliptic::BoundaryConditions::BoundaryCondition<2> { 38 : private: 39 0 : using Base = elliptic::BoundaryConditions::BoundaryCondition<2>; 40 0 : using GradTensorType = 41 : TensorMetafunctions::prepend_spatial_index<tnsr::aa<ComplexDataVector, 3>, 42 : 2, UpLo::Lo, Frame::Inertial>; 43 : 44 : public: 45 0 : struct MModeNumber { 46 0 : static constexpr Options::String help = 47 : "Mode number 'm' of the metric perturbation"; 48 0 : using type = int; 49 : }; 50 : 51 0 : static constexpr Options::String help = "Angular boundary condition"; 52 0 : using options = tmpl::list<MModeNumber>; 53 : 54 0 : Angular() = default; 55 0 : Angular(const Angular&) = default; 56 0 : Angular& operator=(const Angular&) = default; 57 0 : Angular(Angular&&) = default; 58 0 : Angular& operator=(Angular&&) = default; 59 0 : ~Angular() override = default; 60 : 61 0 : explicit Angular(int m_mode_number); 62 : 63 0 : int m_mode_number() const { return m_mode_number_; } 64 : 65 : /// \cond 66 : explicit Angular(CkMigrateMessage* m); 67 : using PUP::able::register_constructor; 68 : WRAPPED_PUPable_decl_template(Angular); 69 : /// \endcond 70 : 71 0 : std::unique_ptr<domain::BoundaryConditions::BoundaryCondition> get_clone() 72 : const override { 73 : return std::make_unique<Angular>(*this); 74 : } 75 : 76 0 : std::vector<elliptic::BoundaryConditionType> boundary_condition_types() 77 : const override { 78 : // For m > 0 some tensor components are Neumann-type and others Dirichlet. 79 : // The boundary condition type is currently only used for the 80 : // `MinusLaplacian` subdomain preconditioner, so its effectiveness will be 81 : // lower unless we extend this function to return a type for each tensor 82 : // component. 83 : return {m_mode_number_ == 0 ? elliptic::BoundaryConditionType::Neumann 84 : : elliptic::BoundaryConditionType::Dirichlet}; 85 : } 86 : 87 0 : using argument_tags = tmpl::list<>; 88 0 : using volume_tags = tmpl::list<>; 89 : 90 0 : void apply( 91 : gsl::not_null<tnsr::aa<ComplexDataVector, 3>*> field, 92 : gsl::not_null<tnsr::aa<ComplexDataVector, 3>*> n_dot_field_gradient, 93 : const GradTensorType& deriv_field) const; 94 : 95 0 : using argument_tags_linearized = tmpl::list<>; 96 0 : using volume_tags_linearized = tmpl::list<>; 97 : 98 0 : void apply_linearized( 99 : gsl::not_null<tnsr::aa<ComplexDataVector, 3>*> field_correction, 100 : gsl::not_null<tnsr::aa<ComplexDataVector, 3>*> 101 : n_dot_field_correction_gradient, 102 : const GradTensorType& deriv_field_correction) const; 103 : 104 : // NOLINTNEXTLINE 105 0 : void pup(PUP::er& p) override; 106 : 107 : private: 108 0 : friend bool operator==(const Angular& lhs, const Angular& rhs); 109 : 110 0 : int m_mode_number_{}; 111 : }; 112 : 113 0 : bool operator!=(const Angular& lhs, const Angular& rhs); 114 : 115 : } // namespace GrSelfForce::BoundaryConditions