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