SpECTRE  v2024.04.12
Control System

Contains control system elements. More...

Namespaces

namespace  control_system
 Control systems and related functionality.
 
namespace  control_system::Actions
 All Actions related to the control system.
 
namespace  control_system::ControlErrors
 All control errors that will be used in control systems.
 
namespace  control_system::Systems
 All control systems.
 
namespace  control_system::size
 Classes and functions used in implementation of size control.
 
namespace  control_system::protocols
 Protocols for control systems.
 
namespace  control_system::OptionTags
 All option tags related to the control system.
 
namespace  control_system::QueueTags
 All tags that will be used in the LinkedMessageQueue's within control systems.
 
namespace  control_system::Tags
 All DataBox tags related to the control system.
 
namespace  control_system::metafunctions
 Metafunctions associated with the control systems.
 

Classes

struct  control_system::Actions::Initialize< Metavariables, ControlSystem >
 Initialize items related to the control system. More...
 
class  Averager< DerivOrder >
 A weighted exponential averager of \(Q\) and its derivatives implementing Appendix A in [87]. More...
 
struct  ControlComponent< Metavariables, ControlSystem >
 The singleton parallel component responsible for managing a single control system. More...
 
class  Controller< DerivOrder >
 A PND (proportional to Q and N derivatives of Q) controller that computes the control signal: More...
 
struct  control_system::measurements::Tags::NeutronStarCenter< Center >
 DataBox tag for location of neutron star center (or more accurately, center of mass of the matter in the x>0 (label A) or x<0 (label B) region, in grid coordinates). More...
 
struct  control_system::RunCallbacks< Submeasurement, ControlSystems >
 Apply the process_measurement struct of each of the ControlSystems to the result of the Submeasurement. More...
 
struct  control_system::Tags::FunctionsOfTimeInitialize
 The FunctionsOfTime initialized from a DomainCreator, initial time, and control system OptionHolders. More...
 
struct  control_system::Tags::IsActiveMap
 Tag that holds a map between control system name and whether that control system is active. Can be used in the GlobalCache. More...
 
struct  control_system::Tags::MeasurementTimescales
 The measurement timescales associated with domain::Tags::FunctionsOfTime. More...
 
struct  control_system::OptionHolder< ControlSystem >
 Holds all options for a single control system. More...
 
struct  control_system::OptionTags::ControlSystemGroup
 Options group for all control system options. More...
 
struct  control_system::OptionTags::ControlSystemInputs< ControlSystem >
 Option tag for each individual control system. The name of this option is the name of the ControlSystem struct it is templated on. This way all control systems will have a unique name. More...
 
struct  control_system::OptionTags::WriteDataToDisk
 Option tag on whether to write data to disk. More...
 
struct  control_system::OptionTags::MeasurementsPerUpdate
 Option tag that determines how many measurements will occur per control system update. More...
 
struct  control_system::OptionTags::Verbosity
 Verbosity tag for printing diagnostics about the control system algorithm. This does not control when data is written to disk. More...
 
struct  control_system::QueueTags::Center< Horizon >
 Holds the centers of each horizon from measurements as DataVectors. More...
 
struct  control_system::QueueTags::Horizon< Frame >
 Holds a full strahlkorper from measurements that represents a horizon. More...
 
struct  control_system::QueueTags::ExcisionSurface< Frame >
 Holds a full strahlkorper from measurements for the excision surface. More...
 
struct  control_system::QueueTags::LapseOnExcisionSurface
 Holds the lapse on the ExcisionSurface More...
 
struct  control_system::QueueTags::ShiftyQuantity< Frame >
 Holds a quantity that's similar to the shift, but isn't the shift, on the ExcisionSurface. More...
 
struct  control_system::QueueTags::SpatialMetricOnExcisionSurface< Frame >
 Holds the spatial metric on the ExcisionSurface More...
 
struct  control_system::QueueTags::InverseSpatialMetricOnExcisionSurface< Frame >
 Holds the inverse spatial metric on the ExcisionSurface More...
 
struct  control_system::QueueTags::SizeExcisionQuantities< Frame >
 A queue tag that holds a TaggedTuple of all quantities needed for the excision measurement of size control. More...
 
struct  control_system::QueueTags::SizeHorizonQuantities< Frame >
 A queue tag that holds a TaggedTuple of all quantities needed for the horizon measurement of size control. More...
 
struct  control_system::Tags::WriteDataToDisk
 DataBox tag for writing control system data to disk. More...
 
struct  control_system::Tags::ObserveCenters
 DataBox tag for writing the centers of the horizons to disk. More...
 
struct  control_system::Tags::Averager< ControlSystem >
 DataBox tag for the averager. More...
 
struct  control_system::Tags::TimescaleTuner< ControlSystem >
 DataBox tag for the timescale tuner. More...
 
struct  control_system::Tags::Controller< ControlSystem >
 DataBox tag for the controller. More...
 
struct  control_system::Tags::ControlError< ControlSystem >
 DataBox tag for the control error. More...
 
struct  control_system::Tags::MeasurementsPerUpdate
 Tag that determines how many measurements will occur per control system update. This will usually be stored in the global cache. More...
 
struct  control_system::Tags::CurrentNumberOfMeasurements
 DataBox tag that keeps track of which measurement we are on. More...
 
struct  control_system::Tags::Verbosity
 DataBox tag that holds the verbosity used to print info about the control system algorithm. More...
 
class  TimescaleTuner< AllowDecrease >
 Manages control system timescales. More...
 
struct  control_system::UpdateSingleFunctionOfTime
 Updates a FunctionOfTime in the global cache. Intended to be used in Parallel::mutate. More...
 
struct  control_system::UpdateMultipleFunctionsOfTime
 Updates several FunctionOfTimes in the global cache at once. Intended to be used in Parallel::mutate. More...
 
class  domain::FunctionsOfTime::FixedSpeedCubic
 Sets \(f(t)\) and derivatives using cubic rational functions, such that the first derivative approaches a constant and the second derivative approaches zero. More...
 
class  domain::FunctionsOfTime::SettleToConstant
 Given an initial function of time, transitions the map to a constant-in-time value. More...
 
class  domain::FunctionsOfTime::SettleToConstantQuaternion
 Given an initial function of time that is a unit quaternion, transitions to a constant-in-time unit quaternion. More...
 

Typedefs

template<typename Metavariables , typename ControlSystems >
using control_system::control_components = tmpl::transform< ControlSystems, tmpl::bind< ControlComponent, tmpl::pin< Metavariables >, tmpl::_1 > >
 List of control components to be added to the component list of the metavars.
 
template<typename ControlSystems >
using control_system::metafunctions::control_system_events = tmpl::flatten< tmpl::transform< metafunctions::measurements_t< ControlSystems >, detail::events_from_measurement< tmpl::pin< ControlSystems >, tmpl::_1 > > >
 The list of events needed for measurements for a list of control systems.
 
template<typename ControlSystems >
using control_system::inputs = tmpl::transform< ControlSystems, tmpl::bind< OptionTags::ControlSystemInputs, tmpl::_1 > >
 Alias to get all the option holders from a list of control systems. This is useful in the option_tags alias of simple tags for getting all the options from control systems.
 
template<typename ControlSystems >
using control_system::control_system_triggers = tmpl::transform< metafunctions::measurements_t< ControlSystems >, tmpl::bind< Trigger, metafunctions::control_systems_with_measurement< tmpl::pin< ControlSystems >, tmpl::_1 > > >
 The list of triggers needed for measurements for a list of control systems.
 

Functions

template<size_t DerivOrder, bool AllowDecrease>
DataVector control_system::calculate_measurement_timescales (const ::Controller< DerivOrder > &controller, const ::TimescaleTuner< AllowDecrease > &tuner, const int measurements_per_update)
 Calculate the measurement timescale based on the damping timescale, update fraction, and DerivOrder of the control system. More...
 
double control_system::function_of_time_expiration_time (const double time, const DataVector &old_measurement_timescales, const DataVector &new_measurement_timescales, const int measurements_per_update)
 Calculate the next expiration time for the FunctionsOfTime. More...
 
double control_system::measurement_expiration_time (const double time, const DataVector &old_measurement_timescales, const DataVector &new_measurement_timescales, const int measurements_per_update)
 Calculate the next expiration time for the MeasurementTimescales. More...
 
template<size_t Dim, typename... OptionHolders>
std::unordered_map< std::string, double > control_system::initial_expiration_times (const double initial_time, const int measurements_per_update, const std::unique_ptr<::DomainCreator< Dim > > &domain_creator, const OptionHolders &... option_holders)
 Construct the initial expiration times for functions of time that are controlled by a control system. More...
 
template<typename ControlSystem , typename Metavariables >
void control_system::write_components_to_disk (const double time, Parallel::GlobalCache< Metavariables > &cache, const std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > &function_of_time, const std::array< DataVector, 2 > &q_and_dtq, const DataVector &timescales)
 Writes all components of a function of time to disk at a specific time from a control system after it updates the functions of time. More...
 

Detailed Description

Contains control system elements.

The control system manages the time-dependent mapping between frames, such as the fixed computational frame (grid frame) and the inertial frame. The time-dependent parameters of the mapping are adjusted by a feedback control system in order to follow the dynamical evolution of objects such as horizons of black holes or surfaces of neutron stars. For example, in binary black hole simulations the map is typically a composition of maps that include translation, rotation, scaling, shape, etc. Each map under the governance of the control system has an associated time-dependent map parameter \(\lambda(t)\) that is a piecewise Nth order polynomial. At discrete times (called reset times), the control system resets the Nth time derivative of \(\lambda(t)\) to a new constant value, in order to minimize an error function \(Q(t)\) that is specific to each map. At each reset time, the Nth derivative of \(\lambda(t)\) is set to a function \(U(t)\), called the control signal, that is determined by \(Q(t)\) and its time derivatives and time integral. Note that \(\lambda(t)\), \(U(t)\), and \(Q(t)\) can be vectors.

The key components of the control system are:

For additional details describing our control system approach, see [87].

Function Documentation

◆ calculate_measurement_timescales()

template<size_t DerivOrder, bool AllowDecrease>
DataVector control_system::calculate_measurement_timescales ( const ::Controller< DerivOrder > &  controller,
const ::TimescaleTuner< AllowDecrease > &  tuner,
const int  measurements_per_update 
)

Calculate the measurement timescale based on the damping timescale, update fraction, and DerivOrder of the control system.

The update timescale is \(\tau_\mathrm{update} = \alpha_\mathrm{update} \tau_\mathrm{damp}\) where \(\tau_\mathrm{damp}\) is the damping timescale (from the TimescaleTuner) and \(\alpha_\mathrm{update}\) is the update fraction (from the controller). For an Nth order control system, the averager requires at least N measurements in order to perform its finite differencing to calculate the derivatives of the control error. This implies that the largest the measurement timescale can be is \(\tau_\mathrm{m} = \tau_\mathrm{update} / N\). To ensure that we have sufficient measurements, we calculate the measurement timescales as \(\tau_\mathrm{m} = \tau_\mathrm{update} / N\) where \(N\) is measurements_per_update.

◆ function_of_time_expiration_time()

double control_system::function_of_time_expiration_time ( const double  time,
const DataVector old_measurement_timescales,
const DataVector new_measurement_timescales,
const int  measurements_per_update 
)

Calculate the next expiration time for the FunctionsOfTime.

\begin{align} T_\mathrm{expr}^\mathrm{FoT} &= t + \tau_\mathrm{m}^\mathrm{old} + N * \tau_\mathrm{m}^\mathrm{new} \\ \end{align}

where \(T_\mathrm{expr}^\mathrm{FoT}\) is the expiration time for the FunctionsOfTime, \(t\) is the update time, \(\tau_\mathrm{m}^\mathrm{old/new}\) is the measurement timescale, and \(N\) is the number of measurements per update.

The expiration is calculated this way because we update the functions of time one (old) measurement before they actually expire.

The choice of having the functions of time expire exactly one old measurement after they are updated is arbitrary. They could expire any time between the update time and one old measurement after the update. This decision was made to minimize time spent waiting for the functions of time to be valid.

Since functions of time are valid at their expiration time, we are actually able to do the next measurement if the expiration time is at that measurement. Thus we delay any potential waiting that may happen until the subsequent measurement (and by that time, most, if not all, functions of time should have been updated because an entire horizon find happened in the meantime). If the expiration time was earlier than the next measurement, we'd have to pause the Algorithm on the DG elements and wait until all the functions of time have been updated.

◆ initial_expiration_times()

template<size_t Dim, typename... OptionHolders>
std::unordered_map< std::string, double > control_system::initial_expiration_times ( const double  initial_time,
const int  measurements_per_update,
const std::unique_ptr<::DomainCreator< Dim > > &  domain_creator,
const OptionHolders &...  option_holders 
)

Construct the initial expiration times for functions of time that are controlled by a control system.

The expiration times are constructed using inputs from control system OptionHolders as an unordered map from the name of the function of time being controlled to the expiration time.

The expiration time for each individual function of time is computed as \(\tau_\mathrm{exp} = \alpha_\mathrm{update} \tau_\mathrm{damp}\) where \(\alpha_\mathrm{update}\) is the update fraction supplied as input to the Controller and \(\tau_\mathrm{damp}\) is/are the damping timescales supplied from the TimescaleTuner ( \(\tau_\mathrm{damp}\) is a DataVector with as many components as the corresponding function of time, thus \(\tau_\mathrm{exp}\) will also be a DataVector of the same length).

However, this expiration time calculated above is not necessarily the expiration that is returned by this function. We group functions of time by the control_system::protocols::Measurement that their corresponding control systems use. This is because one measurement may be used to update many functions of time. So the actual expiration time that is used for all the functions of time in this group is the minimum of the \(\tau_\mathrm{exp}\) of each function of time in the group.

These groups are calculated using control_system::system_to_combined_names where the list of control systems comes from the passed in OptionHolders.

If the control system isn't active then expiration time is std::numeric_limits<double>::infinity(), regardless of what the groups' expiration time is.

◆ measurement_expiration_time()

double control_system::measurement_expiration_time ( const double  time,
const DataVector old_measurement_timescales,
const DataVector new_measurement_timescales,
const int  measurements_per_update 
)

Calculate the next expiration time for the MeasurementTimescales.

\begin{align} T_\mathrm{expr}^\mathrm{m} &= T_\mathrm{expr}^\mathrm{FoT} - \frac{1}{2} \tau_\mathrm{m}^\mathrm{new} \\ \end{align}

where \(T_\mathrm{expr}^\mathrm{m}\) is the measurement expiration time, \(T_\mathrm{expr}^\mathrm{FoT}\) is the function of time expiration time as calculate from function_of_time_expiration_time(), and \(\tau_\mathrm{m}^\mathrm{new}\) is the new measurement timescale. The reason for the factor of a half is as follows:

We update the functions of time one (old) measurement before the expiration time. Based on how dense triggers are set up, which control_system::Trigger is a dense trigger, you calculate the next trigger (measurement) time at the current measurement time. However, at the function of time expiration time we need updated damping timescales from all control systems in order to calculate when the next measurement is going to be (and in turn, the next measurement expiration time). Thus, at the measurement that occurs at the function of time expiration time, our measurement timescales can't be valid and we must wait for updated ones. To achieve this, we set the measurement expiration time before the function of time expiration time, but after the previous measurement (the update measurement). The factor of one half is just to guarantee we are more than epsilon before the function of time expiration time and more than epsilon after the update measurement.

◆ write_components_to_disk()

template<typename ControlSystem , typename Metavariables >
void control_system::write_components_to_disk ( const double  time,
Parallel::GlobalCache< Metavariables > &  cache,
const std::unique_ptr< domain::FunctionsOfTime::FunctionOfTime > &  function_of_time,
const std::array< DataVector, 2 > &  q_and_dtq,
const DataVector timescales 
)

Writes all components of a function of time to disk at a specific time from a control system after it updates the functions of time.

Details

The columns of data written are:

  • Time
  • FunctionOfTime
  • dtFunctionOfTime
  • d2tFunctionOfTime
  • ControlError
  • dtControlError
  • DampingTimescale

Data will be stored in the reduction file. All subfiles for the control system within the H5 file will be under the group "/ControlSystems". Within this group, there will be one group for each control system. The name of each group will be the result of the name() function from each control system. An example would look like

  • /ControlSystems/SystemA
  • /ControlSystems/SystemB
  • /ControlSystems/SystemC

Then, within each system group, there will be one subfile for each component of the function of time that is being controlled. The name of this subfile is the name of the component. The name of each component will be the result of the component_name(i) function from the control system, where i is the index of the component. For example, if "SystemA" has 3 components with names "X", "Y", and "Z", then the subfiles would look like

  • /ControlSystems/SystemA/X.dat
  • /ControlSystems/SystemA/Y.dat
  • /ControlSystems/SystemA/Z.dat