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 "DataStructures/TaggedTuple.hpp"
25 : #include "Domain/Creators/DomainCreator.hpp"
26 : #include "ParallelAlgorithms/ApparentHorizonFinder/Tags.hpp"
27 : #include "Time/OptionTags/InitialTime.hpp"
28 : #include "Utilities/ErrorHandling/Error.hpp"
29 : #include "Utilities/Gsl.hpp"
30 : #include "Utilities/ProtocolHelpers.hpp"
31 : #include "Utilities/StdHelpers.hpp"
32 : #include "Utilities/TMPL.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
|