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
|