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 <map> 8 : #include <memory> 9 : #include <optional> 10 : #include <string> 11 : #include <unordered_map> 12 : #include <utility> 13 : 14 : #include "ControlSystem/Averager.hpp" 15 : #include "ControlSystem/CombinedName.hpp" 16 : #include "ControlSystem/Controller.hpp" 17 : #include "ControlSystem/IsSize.hpp" 18 : #include "ControlSystem/Metafunctions.hpp" 19 : #include "ControlSystem/Protocols/ControlSystem.hpp" 20 : #include "ControlSystem/Tags/OptionTags.hpp" 21 : #include "ControlSystem/TimescaleTuner.hpp" 22 : #include "ControlSystem/UpdateFunctionOfTime.hpp" 23 : #include "DataStructures/DataBox/Tag.hpp" 24 : #include "Domain/Creators/DomainCreator.hpp" 25 : #include "ParallelAlgorithms/ApparentHorizonFinder/Tags.hpp" 26 : #include "Time/OptionTags/InitialTime.hpp" 27 : #include "Utilities/ErrorHandling/Error.hpp" 28 : #include "Utilities/Gsl.hpp" 29 : #include "Utilities/ProtocolHelpers.hpp" 30 : #include "Utilities/StdHelpers.hpp" 31 : #include "Utilities/TMPL.hpp" 32 : #include "Utilities/TaggedTuple.hpp" 33 : #include "Utilities/TypeTraits/CreateHasStaticMemberVariable.hpp" 34 : 35 : /// \cond 36 : template <class Metavariables, typename ControlSystem> 37 : struct ControlComponent; 38 : namespace control_system { 39 : template <typename ControlSystem> 40 : struct OptionHolder; 41 : } // namespace control_system 42 : namespace domain::OptionTags { 43 : template <size_t Dim> 44 : struct DomainCreator; 45 : } // namespace domain::OptionTags 46 : namespace OptionTags { 47 : struct InitialTime; 48 : } // namespace OptionTags 49 : /// \endcond 50 : 51 : /// \ingroup ControlSystemGroup 52 : /// All DataBox tags related to the control system 53 : namespace control_system::Tags { 54 : /// \ingroup DataBoxTagsGroup 55 : /// \ingroup ControlSystemGroup 56 : /// DataBox tag for writing control system data to disk 57 1 : struct WriteDataToDisk : db::SimpleTag { 58 0 : using type = bool; 59 0 : using option_tags = tmpl::list<OptionTags::WriteDataToDisk>; 60 : 61 0 : static constexpr bool pass_metavariables = false; 62 0 : static type create_from_options(const type& option) { return option; } 63 : }; 64 : 65 0 : using ObserveCenters = ah::Tags::ObserveCenters; 66 : 67 : /// \ingroup DataBoxTagsGroup 68 : /// \ingroup ControlSystemGroup 69 : /// DataBox tag for the averager 70 : /// 71 : /// To compute the `deriv_order`th derivative of a control error, the max 72 : /// derivative we need from the averager is the `deriv_order - 1`st derivative. 73 : /// 74 : /// If the option holder is nullopt, constructs a default Averager. 75 : template <typename ControlSystem> 76 1 : struct Averager : db::SimpleTag { 77 0 : using type = ::Averager<ControlSystem::deriv_order - 1>; 78 : 79 0 : using option_tags = 80 : tmpl::list<OptionTags::ControlSystemInputs<ControlSystem>>; 81 0 : static constexpr bool pass_metavariables = false; 82 0 : static type create_from_options( 83 : const std::optional<control_system::OptionHolder<ControlSystem>>& 84 : option_holder) { 85 : return option_holder.has_value() ? option_holder->averager : type{}; 86 : } 87 : }; 88 : 89 : namespace detail { 90 : template <bool AllowDecrease, size_t Dim> 91 : void initialize_tuner( 92 : gsl::not_null<::TimescaleTuner<AllowDecrease>*> tuner, 93 : const std::unique_ptr<::DomainCreator<Dim>>& domain_creator, 94 : const double initial_time, const std::string& name); 95 : } // namespace detail 96 : 97 : /// \ingroup DataBoxTagsGroup 98 : /// \ingroup ControlSystemGroup 99 : /// DataBox tag for the timescale tuner 100 : /// 101 : /// If the option holder is nullopt, constructs a default TimescaleTuner. 102 : template <typename ControlSystem> 103 1 : struct TimescaleTuner : db::SimpleTag { 104 : private: 105 0 : static constexpr bool is_size = 106 : control_system::size::is_size_v<ControlSystem>; 107 : 108 : public: 109 0 : using type = ::TimescaleTuner<not is_size>; 110 : 111 : template <typename Metavariables> 112 0 : using option_tags = 113 : tmpl::list<OptionTags::ControlSystemInputs<ControlSystem>, 114 : domain::OptionTags::DomainCreator<Metavariables::volume_dim>, 115 : ::OptionTags::InitialTime>; 116 0 : static constexpr bool pass_metavariables = true; 117 : 118 : template <typename Metavariables> 119 0 : static type create_from_options( 120 : const std::optional<control_system::OptionHolder<ControlSystem>>& 121 : option_holder, 122 : const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>& 123 : domain_creator, 124 : const double initial_time) { 125 : if (not option_holder.has_value()) { 126 : return type{}; 127 : } 128 : 129 : auto tuner = option_holder->tuner; 130 : detail::initialize_tuner(make_not_null(&tuner), domain_creator, 131 : initial_time, ControlSystem::name()); 132 : return tuner; 133 : } 134 : }; 135 : 136 : /// \ingroup DataBoxTagsGroup 137 : /// \ingroup ControlSystemGroup 138 : /// DataBox tag for the controller 139 : /// 140 : /// If the option holder is nullopt, constructs a default Controller. 141 : template <typename ControlSystem> 142 1 : struct Controller : db::SimpleTag { 143 0 : using type = ::Controller<ControlSystem::deriv_order>; 144 : 145 : template <typename Metavariables> 146 0 : using option_tags = 147 : tmpl::list<OptionTags::ControlSystemInputs<ControlSystem>, 148 : domain::OptionTags::DomainCreator<Metavariables::volume_dim>, 149 : ::OptionTags::InitialTime>; 150 0 : static constexpr bool pass_metavariables = true; 151 : 152 : template <typename Metavariables> 153 0 : static type create_from_options( 154 : const std::optional<control_system::OptionHolder<ControlSystem>>& 155 : option_holder, 156 : const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>& 157 : domain_creator, 158 : const double initial_time) { 159 : if (not option_holder.has_value()) { 160 : return type{}; 161 : } 162 : 163 : type controller = option_holder->controller; 164 : auto tuner = option_holder->tuner; 165 : detail::initialize_tuner(make_not_null(&tuner), domain_creator, 166 : initial_time, ControlSystem::name()); 167 : 168 : controller.set_initial_update_time(initial_time); 169 : controller.assign_time_between_updates(min(tuner.current_timescale())); 170 : 171 : return controller; 172 : } 173 : }; 174 : 175 : /// \ingroup DataBoxTagsGroup 176 : /// \ingroup ControlSystemGroup 177 : /// DataBox tag for the control error 178 : /// 179 : /// If the option holder is nullopt, constructs a default ControlError. 180 : template <typename ControlSystem> 181 1 : struct ControlError : db::SimpleTag { 182 0 : using type = typename ControlSystem::control_error; 183 : 184 0 : using option_tags = 185 : tmpl::list<OptionTags::ControlSystemInputs<ControlSystem>>; 186 0 : static constexpr bool pass_metavariables = false; 187 : 188 0 : static type create_from_options( 189 : const std::optional<control_system::OptionHolder<ControlSystem>>& 190 : option_holder) { 191 : return option_holder.has_value() ? option_holder->control_error : type{}; 192 : } 193 : }; 194 : 195 : /// \ingroup DataBoxTagsGroup 196 : /// \ingroup ControlSystemGroup 197 : /// Tag that determines how many measurements will occur per control 198 : /// system update. This will usually be stored in the global cache. 199 1 : struct MeasurementsPerUpdate : db::SimpleTag { 200 0 : using type = int; 201 : 202 0 : using option_tags = tmpl::list<OptionTags::MeasurementsPerUpdate>; 203 0 : static constexpr bool pass_metavariables = false; 204 0 : static int create_from_options(const int measurements_per_update) { 205 : return measurements_per_update; 206 : } 207 : }; 208 : 209 : /// \ingroup DataBoxTagsGroup 210 : /// \ingroup ControlSystemGroup 211 : /// Tag that determines whether FunctionOfTime updates will be delayed 212 : /// by one measurement. This will usually be stored in the global 213 : /// cache. 214 1 : struct DelayUpdate : db::SimpleTag { 215 0 : using type = bool; 216 : 217 0 : using option_tags = tmpl::list<OptionTags::DelayUpdate>; 218 0 : static constexpr bool pass_metavariables = false; 219 0 : static type create_from_options(const bool delay_update) { 220 : return delay_update; 221 : } 222 : }; 223 : 224 : /// \ingroup DataBoxTagsGroup 225 : /// \ingroup ControlSystemGroup 226 : /// DataBox tag that keeps track of which measurement we are on. 227 1 : struct CurrentNumberOfMeasurements : db::SimpleTag { 228 0 : using type = int; 229 : }; 230 : 231 : /// \ingroup DataBoxTagsGroup 232 : /// \ingroup ControlSystemGroup 233 : /// DataBox tag that holds the verbosity used to print info about the control 234 : /// system algorithm. 235 1 : struct Verbosity : db::SimpleTag { 236 0 : using type = ::Verbosity; 237 : 238 0 : using option_tags = tmpl::list<OptionTags::Verbosity>; 239 0 : static constexpr bool pass_metavariables = false; 240 0 : static type create_from_options(const ::Verbosity verbosity) { 241 : return verbosity; 242 : } 243 : }; 244 : 245 : /*! 246 : * \brief Tag meant to be stored in the GlobalCache that stores a map between 247 : * names of control systems and the "combined" name that that control system is 248 : * part of. 249 : * 250 : * \details The "combined" name for each control system is computed using 251 : * `control_system::system_to_combined_names` where the list of control systems 252 : * is taken from the `component_list` type alias of the metavariables. Each 253 : * "combined" name corresponds to a different 254 : * `control_system::protocols::Measurement`. 255 : */ 256 1 : struct SystemToCombinedNames : db::SimpleTag { 257 0 : using type = std::unordered_map<std::string, std::string>; 258 : 259 : template <typename Metavariables> 260 0 : using option_tags = tmpl::list<>; 261 0 : static constexpr bool pass_metavariables = true; 262 : 263 : private: 264 : template <typename Component> 265 0 : using system = typename Component::control_system; 266 : 267 : public: 268 : template <typename Metavariables> 269 0 : static type create_from_options() { 270 : using all_control_components = 271 : metafunctions::all_control_components<Metavariables>; 272 : using all_control_systems = 273 : tmpl::transform<all_control_components, tmpl::bind<system, tmpl::_1>>; 274 : 275 : return system_to_combined_names<all_control_systems>(); 276 : } 277 : }; 278 : 279 : /*! 280 : * \brief Map between "combined" names and the 281 : * `control_system::UpdateAggregator`s that go with each. 282 : */ 283 1 : struct UpdateAggregators : db::SimpleTag { 284 0 : using type = 285 : std::unordered_map<std::string, control_system::UpdateAggregator>; 286 : }; 287 : } // namespace control_system::Tags