Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <cstddef>
8 : #include <limits>
9 : #include <optional>
10 : #include <utility>
11 : #include <variant>
12 :
13 : #include "DataStructures/DataVector.hpp"
14 : #include "Options/String.hpp"
15 :
16 : /// \cond
17 : namespace PUP {
18 : class er;
19 : }
20 : /// \endcond
21 :
22 : /*!
23 : * \ingroup ControlSystemGroup
24 : * \brief Manages control system timescales
25 : *
26 : * The TimescaleTuner adjusts the damping timescale, \f$\tau\f$, of the control
27 : * system.\n The damping timescale is restricted to
28 : * `min_timescale`\f$\le\tau\le\f$`max_timescale`
29 : *
30 : * The damping time is adjusted according to the following criteria:
31 : *
32 : * **Decrease** the timescale by a factor of `decrease_factor` if either \n
33 : * - the error is too large: \f$|Q| >\f$ `decrease_timescale_threshold`
34 : * OR
35 : * the error is changing quickly: \f$|\dot{Q}|\tau >\f$
36 : * `decrease_timescale_threshold`,\n
37 : * AND \n
38 : * - the error is growing: \f$\dot{Q}Q > 0\f$
39 : * OR
40 : * the expected change in \f$Q\f$ is less than half its current value:
41 : * \f$|\dot{Q}|\tau < |Q|/2\f$
42 : *
43 : * **Increase** the timescale by a factor of `increase_factor` if \n
44 : * - the error is sufficiently small: \f$|Q|<\f$ `increase_timescale_threshold`
45 : * \n
46 : * AND \n
47 : * - the expected change in \f$Q\f$ is less than the threshold:
48 : * \f$|\dot{Q}|\tau < \f$ `increase_timescale_threshold`
49 : *
50 : * If the template bool \p AllowDecrease is false, then the check for decreasing
51 : * the timescale will be ignored. This can be used if something else will be
52 : * controlling the decrease of the timescale.
53 : */
54 : template <bool AllowDecrease>
55 1 : class TimescaleTuner {
56 : public:
57 0 : static constexpr Options::String help{
58 : "TimescaleTuner: stores and dynamically updates the timescales for each "
59 : "component of a particular control system."};
60 0 : struct InitialTimescales {
61 0 : using type = std::variant<double, std::vector<double>>;
62 0 : static constexpr Options::String help = {
63 : "Initial timescales for each function of time. Can either be a single "
64 : "value which will be used for all components of a function of time, or "
65 : "a vector of values. The vector must have the same number of "
66 : "components as the function of time."};
67 : };
68 :
69 0 : struct MinTimescale {
70 0 : using type = double;
71 0 : static constexpr Options::String help = {"Minimum timescale"};
72 : };
73 :
74 0 : struct MaxTimescale {
75 0 : using type = double;
76 0 : static constexpr Options::String help = {"Maximum timescale"};
77 : };
78 :
79 0 : struct DecreaseThreshold {
80 0 : using type = double;
81 0 : static constexpr Options::String help = {
82 : "Threshold for decrease of timescale"};
83 : };
84 0 : struct IncreaseThreshold {
85 0 : using type = double;
86 0 : static constexpr Options::String help = {
87 : "Threshold for increase of timescale"};
88 : };
89 0 : struct IncreaseFactor {
90 0 : using type = double;
91 0 : static constexpr Options::String help = {"Factor to increase timescale"};
92 : };
93 0 : struct DecreaseFactor {
94 0 : using type = double;
95 0 : static constexpr Options::String help = {"Factor to decrease timescale"};
96 : };
97 :
98 0 : using options = tmpl::append<
99 : tmpl::list<InitialTimescales, MaxTimescale, MinTimescale,
100 : IncreaseThreshold, IncreaseFactor>,
101 : tmpl::conditional_t<AllowDecrease,
102 : tmpl::list<DecreaseThreshold, DecreaseFactor>,
103 : tmpl::list<>>>;
104 :
105 0 : TimescaleTuner(
106 : const typename InitialTimescales::type& initial_timescale,
107 : double max_timescale, double min_timescale,
108 : double increase_timescale_threshold, double increase_factor,
109 : double decrease_timescale_threshold = std::numeric_limits<double>::max(),
110 : double decrease_factor = 1.0);
111 :
112 0 : TimescaleTuner() = default;
113 0 : TimescaleTuner(TimescaleTuner&&) = default;
114 0 : TimescaleTuner& operator=(TimescaleTuner&&) = default;
115 0 : TimescaleTuner(const TimescaleTuner&) = default;
116 0 : TimescaleTuner& operator=(const TimescaleTuner&) = default;
117 0 : ~TimescaleTuner() = default;
118 :
119 : /// Returns the current timescale for each component of a FunctionOfTime
120 1 : const DataVector& current_timescale() const;
121 : /// Manually sets all timescales to a specified value, unless the value is
122 : /// outside of the specified minimum and maximum timescale bounds, in which
123 : /// case it is set to the nearest bounded value.
124 1 : void set_timescale_if_in_allowable_range(double suggested_timescale);
125 : /// The update function responsible for modifying the timescale based on
126 : /// the control system errors
127 1 : void update_timescale(const std::array<DataVector, 2>& q_and_dtq);
128 :
129 : /// Return whether the timescales have been set
130 1 : bool timescales_have_been_set() const { return timescales_have_been_set_; }
131 :
132 : /// \brief Destructively resize the DataVector of timescales. All previous
133 : /// timescale information will be lost.
134 : /// \param num_timescales Number of components to resize to. Can be larger or
135 : /// smaller than the previous size. Must be greater than 0.
136 : /// \param fill_value Optional of what value to use to fill the new
137 : /// timescales. `std::nullopt` signifies to use the minimum of the initial
138 : /// timescales. Default is `std::nullopt`.
139 1 : void resize_timescales(
140 : size_t num_timescales,
141 : const std::optional<double>& fill_value = std::nullopt);
142 :
143 0 : void pup(PUP::er& p);
144 :
145 : template <bool LocalAllowDecrease>
146 0 : friend bool operator==(const TimescaleTuner<LocalAllowDecrease>& lhs,
147 : const TimescaleTuner<LocalAllowDecrease>& rhs);
148 :
149 : private:
150 0 : void check_if_timescales_have_been_set() const;
151 :
152 0 : DataVector timescale_;
153 0 : bool timescales_have_been_set_{false};
154 0 : double initial_timescale_{0.0};
155 0 : double max_timescale_{0.0};
156 0 : double min_timescale_{0.0};
157 0 : double decrease_timescale_threshold_{0.0};
158 0 : double increase_timescale_threshold_{0.0};
159 0 : double increase_factor_{0.0};
160 0 : double decrease_factor_{0.0};
161 : };
162 :
163 : template <bool AllowDecrease>
164 0 : bool operator!=(const TimescaleTuner<AllowDecrease>& lhs,
165 : const TimescaleTuner<AllowDecrease>& rhs);
|