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_{std::numeric_limits<double>::signaling_NaN()}; 155 0 : double max_timescale_; 156 0 : double min_timescale_; 157 0 : double decrease_timescale_threshold_; 158 0 : double increase_timescale_threshold_; 159 0 : double increase_factor_; 160 0 : double decrease_factor_; 161 : }; 162 : 163 : template <bool AllowDecrease> 164 0 : bool operator!=(const TimescaleTuner<AllowDecrease>& lhs, 165 : const TimescaleTuner<AllowDecrease>& rhs);