SpECTRE Documentation Coverage Report
 Current view: top level - ControlSystem - Controller.hpp Hit Total Coverage Commit: 697db44127ce57424c079f629b3283267ec6bd78 Lines: 6 26 23.1 % Date: 2024-06-21 21:13:41 Legend: Lines: hit not hit
  Line data Source code  1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include 7 : #include 8 : #include 9 : 10 : #include "DataStructures/DataVector.hpp" 11 : #include "Options/String.hpp" 12 : 13 : /// \cond 14 : namespace PUP { 15 : class er; 16 : } // namespace PUP 17 : /// \endcond 18 : 19 : /// \ingroup ControlSystemGroup 20 : /// A PND (proportional to Q and N derivatives of Q) controller that computes 21 : /// the control signal: 22 : /// \f[ U(t) = \sum_{k=0}^{N} a_{k} \frac{d^kQ}{dt^k} \f] 23 : /// where N is specified by the template parameter DerivOrder. 24 : /// 25 : /// If an averager is used for q_and_derivs (as we typically do), there is an 26 : /// induced time offset, \f$\Delta t\f$, due to the time-weighted averaging. 27 : /// Therefore, the q_and_derivs that we have in hand are at some time 28 : /// \f$t_{0}\f$. However, we desire q_and_derivs at the current time 29 : /// \f$t = t_{0} + \Delta t\f$ to determine the appropriate control 30 : /// signal. We accomplish this by Taylor expanding 31 : /// \f$Q(t_{0} + \Delta t)\f$. The averager allows for averaging of 32 : /// \f$Q\f$ and its derivatives OR to not average \f$Q\f$ while still averaging 33 : /// the derivatives (the derivatives are always averaged in order to reduce 34 : /// noise due to numerical differentiation). When they are both averaged, the 35 : /// time offset will be identical for \f$Q\f$ and the derivatives, 36 : /// i.e. q_time_offset = deriv_time_offset. If an unaveraged \f$Q\f$ is 37 : /// used, then the time offset associated with \f$Q\f$ is zero, 38 : /// i.e. q_time_offset=0. and the derivative time offset, deriv_time_offset, 39 : /// remains non-zero. 40 : template 41 1 : class Controller { 42 : public: 43 0 : struct UpdateFraction { 44 0 : using type = double; 45 0 : static constexpr Options::String help = { 46 : "Fraction of damping timescale used to determine how often to update " 47 : "functions of time."}; 48 : }; 49 : 50 0 : using options = tmpl::list; 51 0 : static constexpr Options::String help{ 52 : "Computes control signal used to reset highest derivative of a function " 53 : "of time. Also determines when a function of time needs to be updated " 54 : "next."}; 55 : 56 0 : Controller(const double update_fraction) 57 : : update_fraction_(update_fraction) {} 58 : 59 0 : Controller() = default; 60 0 : Controller(Controller&&) = default; 61 0 : Controller& operator=(Controller&&) = default; 62 0 : Controller(const Controller&) = default; 63 0 : Controller& operator=(const Controller&) = default; 64 0 : ~Controller() = default; 65 : 66 0 : DataVector operator()(const double time, const DataVector& timescales, 67 : const std::array& q_and_derivs, 68 : double q_time_offset, double deriv_time_offset); 69 : 70 : /// Takes the current minimum of all timescales for a specific control system 71 : /// and uses that to set the time between updates 72 1 : void assign_time_between_updates(const double current_min_timescale) { 73 : time_between_updates_ = update_fraction_ * current_min_timescale; 74 : } 75 : 76 : /// Returns true if the controller is ready to calculate the control signal 77 1 : bool is_ready(const double time) { 78 : return time >= last_update_time_ + time_between_updates_; 79 : } 80 : 81 : /// Calculates the new expiration time as the old expiration time plus the 82 : /// time between updates 83 1 : double next_expiration_time(const double current_expiration_time) { 84 : return current_expiration_time + time_between_updates_; 85 : } 86 : 87 : /// Sets the last time updated to the initial time 88 1 : void set_initial_update_time(const double initial_time) { 89 : last_update_time_ = initial_time; 90 : } 91 : 92 : /// Return the update fraction 93 1 : double get_update_fraction() const { return update_fraction_; } 94 : 95 : // NOLINTNEXTLINE(google-runtime-references) 96 0 : void pup(PUP::er& p) { 97 : p | update_fraction_; 98 : p | time_between_updates_; 99 : p | last_update_time_; 100 : } 101 : 102 : template 103 : // NOLINTNEXTLINE(readability-redundant-declaration) false positive 104 0 : friend bool operator==(const Controller& lhs, 105 : const Controller& rhs); 106 : 107 : private: 108 : // If update_fraction_ isn't set we need to error 109 0 : double update_fraction_{std::numeric_limits::signaling_NaN()}; 110 : // If this time_between_updates_ isn't set, the default should just be that 111 : // the functions of time are never updated (i.e. infinity) 112 0 : double time_between_updates_{std::numeric_limits::infinity()}; 113 : // Set to a large negative number to signify that we haven't updated yet and 114 : // should as early as possible 115 0 : double last_update_time_{-std::numeric_limits::max()}; 116 : }; 117 : 118 : template 119 0 : bool operator!=(const Controller& lhs, 120 : const Controller& rhs); 

 Generated by: LCOV version 1.14