Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <memory>
7 : #include <optional>
8 : #include <pup.h>
9 : #include <string>
10 :
11 : #include "Utilities/Gsl.hpp"
12 : #include "Utilities/Serialization/CharmPupable.hpp"
13 :
14 : /// \cond
15 : namespace control_system::size {
16 : struct Info;
17 : struct CrossingTimeInfo;
18 : } // namespace control_system::size
19 : /// \endcond
20 :
21 : namespace control_system::size {
22 :
23 : /*!
24 : * \brief Packages some of the inputs to the State::update, so that
25 : * State::update doesn't need a large number of arguments.
26 : */
27 1 : struct StateUpdateArgs {
28 : /// min_char_speed is the minimum over the excision boundary
29 : /// of Eq. 89 of \cite Hemberger2012jz.
30 1 : double min_char_speed;
31 : /// min_comoving_char_speed is the minimum over the excision boundary
32 : /// of Eq. 28 of \cite Hemberger2012jz.
33 1 : double min_comoving_char_speed;
34 : /// horizon_00 is the spherepack coefficient of the apparent
35 : /// horizon.
36 1 : double horizon_00;
37 : /// control_error_delta_r is the control error when the control system
38 : /// is in state Label::DeltaR.
39 : /// This is Q in Eq. 96 of \cite Hemberger2012jz.
40 1 : double control_error_delta_r;
41 : /// average_radial_distance is the average distance between the horizon and
42 : /// the excision boundary. Used only for state DeltaRDriftOutward.
43 : /// If std::nullopt, then DeltaRDriftOutward will not be used.
44 1 : std::optional<double> average_radial_distance;
45 : /// max_allowed_radial_distance is the minimum distance between the horizon
46 : /// and the excision boundary that will trigger state
47 : /// Label::DeltaRDriftOutward. If std::nullopt, then DeltaRDriftOutward
48 : /// will never be triggered.
49 1 : std::optional<double> max_allowed_radial_distance;
50 : /// avg_distorted_normal_dot_unit_coord_vector is the same quantity as
51 : /// ControlErrorArgs::avg_distorted_normal_dot_unit_coord_vector.
52 1 : double avg_distorted_normal_dot_unit_coord_vector;
53 : /// inward_drift_velocity is a positive quantity that represents how
54 : /// fast the horizon and the excision boundary move apart in state
55 : /// DeltaRDriftInward. If std::nullopt, then DeltaRDriftInward will
56 : /// never be triggered.
57 1 : std::optional<double> inward_drift_velocity;
58 : /// min_allowed_radial_distance is the minimum distance between the horizon
59 : /// and the excision boundary that will trigger state
60 : /// Label::DeltaRDriftInward.
61 1 : std::optional<double> min_allowed_radial_distance;
62 : /// min_allowed_char_speed is the minimum char speed that will
63 : /// trigger state DeltaRDriftInward. If both
64 : /// min_allowed_radial_distance and min_allowed_char_speed are
65 : /// std::nullopt, then DeltaRDriftInward will never be triggered.
66 1 : std::optional<double> min_allowed_char_speed;
67 : /// comoving_char_speed_increasing_inward is true if the comoving char speed
68 : /// increases as the excision boundary is moved inward.
69 1 : bool comoving_char_speed_increasing_inward;
70 : };
71 :
72 : /*!
73 : * \brief Packages some of the inputs to the State::control_error, so that
74 : * State::control_error doesn't need a large number of arguments.
75 : */
76 1 : struct ControlErrorArgs {
77 0 : double min_char_speed;
78 0 : double control_error_delta_r;
79 : /*!
80 : * \brief control_error_delta_r_outward is the control error in the
81 : * case DeltaRDriftOutward, the state where there is an outward drift
82 : * caused by too large separation between the horizon and the excision
83 : * boundary. If std::nullopt, then state DeltaRDriftOutward will not be used.
84 : */
85 1 : std::optional<double> control_error_delta_r_outward;
86 : /*!
87 : * \brief avg_distorted_normal_dot_unit_coord_vector is the average of
88 : * distorted_normal_dot_unit_coord_vector over the excision
89 : * boundary.
90 : *
91 : * \details Here distorted_normal_dot_unit_coord_vector is Eq. 93
92 : * of \cite Hemberger2012jz. distorted_normal_dot_unit_coord_vector is
93 : * \f$\hat{n}_i x^i/r\f$ where \f$\nat{n}_i\f$ is the
94 : * distorted-frame unit normal to the excision boundary (pointing
95 : * INTO the hole, i.e. out of the domain), and \f$x^i/r\f$ is the
96 : * distorted-frame (or equivalently the grid frame because it is
97 : * invariant between these two frames because of the required
98 : * limiting behavior of the map we choose) Euclidean normal vector
99 : * from the center of the excision-boundary Strahlkorper to each
100 : * point on the excision-boundary Strahlkorper.
101 : */
102 1 : double avg_distorted_normal_dot_unit_coord_vector;
103 : /*!
104 : * \brief time_deriv_of_lambda_00 is the time derivative of the quantity
105 : * lambda_00 that appears in \cite Hemberger2012jz.
106 : *
107 : * \details time_deriv_of_lambda_00 is (minus) the radial velocity of the
108 : * excision boundary in the distorted frame with respect to the grid frame.
109 : */
110 1 : double time_deriv_of_lambda_00;
111 : };
112 :
113 : /*!
114 : * \brief Represents a 'state' of the size control system.
115 : *
116 : * \details Each 'state' of the size control system has a different control
117 : * signal, which has a different purpose, even though each state
118 : * controls the same map quantity, namely the Y00 coefficient of the
119 : * shape map. For example, state Label::AhSpeed controls
120 : * the Y00 coefficient of the shape map so that the minimum
121 : * characteristic speed is driven towards a target value, and state
122 : * Label::DeltaR controls the Y00 coefficient of the shape
123 : * map (or the Y00 coefficient of a separate spherically-symmetric size
124 : * map) so that the minimum difference between the horizon radius and
125 : * the excision boundary radius is driven towards a constant.
126 : *
127 : * Each state has its own logic (the 'update' function) that
128 : * determines values of certain parameters (i.e. the things in
129 : * Info), including whether the control system should
130 : * transition to a different state.
131 : *
132 : * The different states are:
133 : * - Initial: drives dr/dt of the excision boundary to
134 : * Info::target_drift_velocity.
135 : * - AhSpeed: drives the minimum characteristic speed on the excision boundary
136 : * to Info::target_char_speed.
137 : * - DeltaR: drives the minimum distance between the horizon and the excision
138 : * boundary to be constant in time.
139 : * - DeltaRDriftInward: Same as DeltaR but the excision boundary has a small
140 : * velocity inward. This state is triggered when it is deemed that the
141 : * excision boundary and the horizon are too close to each other; the
142 : * small velocity makes the excision boundary and the horizon drift apart.
143 : * - DeltaRDriftOutward: Same as DeltaR but the excision boundary has a small
144 : * velocity outward. This state is triggered when it is deemed that the
145 : * excision boundary and the horizon are too far apart.
146 : * - DeltaRNoDrift: Same as DeltaR except for the logic that
147 : * determines how DeltaRNoDrift changes to other states.
148 : * DeltaRNoDrift is allowed (under some circumstances) to change
149 : * to state DeltaR, but DeltaRDriftOutward and DeltaRDriftInward
150 : * are never allowed to change to state DeltaR. Instead
151 : * DeltaRDriftOutward and DeltaRDriftInward are allowed (under
152 : * some circumstances) to change to state DeltaRNoDrift.
153 : *
154 : * The reason that DeltaRDriftInward, DeltaRDriftOutward, and
155 : * DeltaRNoDrift are separate states is to simplify the logic. In
156 : * principle, all 3 of those states could be merged with state
157 : * DeltaR, because the control error is the same for all four states
158 : * (except for a velocity term that could be set to zero). But if that
159 : * were done, then there would need to be additional complicated
160 : * logic in determining transitions between different states, and
161 : * that logic would depend not only on the current state, but also on
162 : * the previous state.
163 : */
164 1 : class State : public PUP::able {
165 : public:
166 0 : State() = default;
167 0 : State(const State& /*rhs*/) = default;
168 0 : State& operator=(const State& /*rhs*/) = default;
169 0 : State(State&& /*rhs*/) = default;
170 0 : State& operator=(State&& /*rhs*/) = default;
171 0 : virtual ~State() override = default;
172 :
173 : /// Name of this state
174 1 : virtual std::string name() const = 0;
175 :
176 : /// Return a size_t that corresponds to the state number in SpEC
177 1 : virtual size_t number() const = 0;
178 :
179 0 : virtual std::unique_ptr<State> get_clone() const = 0;
180 : /*!
181 : * \brief Updates the Info in `info`.
182 : *
183 : * \note Notice that `info` includes a state, which might be different than
184 : * the current state upon return. It is the caller's responsibility to check
185 : * if the current state has changed.
186 : *
187 : * \return The return string is used as a helpful diagnostic that may be
188 : * printed to determine what logic decisions the state is making (depends on
189 : * the `control_system::Tags::Verbosity` flag).
190 : */
191 1 : virtual std::string update(
192 : const gsl::not_null<Info*> info, const StateUpdateArgs& update_args,
193 : const CrossingTimeInfo& crossing_time_info) const = 0;
194 : /// Returns the control signal, but does not modify the state or any
195 : /// parameters.
196 1 : virtual double control_error(
197 : const Info& info, const ControlErrorArgs& control_error_args) const = 0;
198 :
199 0 : WRAPPED_PUPable_abstract(State); // NOLINT
200 0 : explicit State(CkMigrateMessage* msg) : PUP::able(msg) {}
201 : };
202 : } // namespace control_system::size
|