SpECTRE
v2024.06.18

Classes and functions used in implementation of size control. More...
Classes  
struct  ControlErrorArgs 
Packages some of the inputs to the State::control_error, so that State::control_error doesn't need a large number of arguments. More...  
struct  CrossingTimeInfo 
Holds information about crossing times, as computed by ZeroCrossingPredictors. More...  
struct  ErrorDiagnostics 
A simple struct to hold diagnostic information about computing the size control error. More...  
struct  Info 
Holds information that is saved between calls of SizeControl. More...  
struct  is_size 
struct  is_size< Systems::Size< Label, DerivOrder > > 
class  State 
Represents a 'state' of the size control system. More...  
struct  StateHistory 
A struct for holding a history of control errors for each state in the control_system::Systems::Size control system. More...  
struct  StateUpdateArgs 
Packages some of the inputs to the State::update, so that State::update doesn't need a large number of arguments. More...  
Functions  
double  control_error_delta_r (const double horizon_00, const double dt_horizon_00, const double lambda_00, const double dt_lambda_00, const double grid_frame_excision_sphere_radius) 
Function that computes the control error for control_system::size::States::DeltaR . More...  
void  comoving_char_speed_derivative (gsl::not_null< Scalar< DataVector > * > result, double lambda_00, double dt_lambda_00, double horizon_00, double dt_horizon_00, double grid_frame_excision_sphere_radius, const tnsr::i< DataVector, 3, Frame::Distorted > &excision_rhat, const tnsr::i< DataVector, 3, Frame::Distorted > &excision_normal_one_form, const Scalar< DataVector > &excision_normal_one_form_norm, const tnsr::I< DataVector, 3, Frame::Distorted > &distorted_components_of_grid_shift, const tnsr::II< DataVector, 3, Frame::Distorted > &inverse_spatial_metric_on_excision_boundary, const tnsr::Ijj< DataVector, 3, Frame::Distorted > &spatial_christoffel_second_kind, const tnsr::i< DataVector, 3, Frame::Distorted > &deriv_lapse, const tnsr::iJ< DataVector, 3, Frame::Distorted > &deriv_of_distorted_shift, const InverseJacobian< DataVector, 3, Frame::Grid, Frame::Distorted > &inverse_jacobian_grid_to_distorted) 
Computes the derivative of the comoving characteristic speed with respect to the size map parameter. More...  
template<typename Frame >  
ErrorDiagnostics  control_error (const gsl::not_null< Info * > info, const gsl::not_null< intrp::ZeroCrossingPredictor * > predictor_char_speed, const gsl::not_null< intrp::ZeroCrossingPredictor * > predictor_comoving_char_speed, const gsl::not_null< intrp::ZeroCrossingPredictor * > predictor_delta_radius, double time, double control_error_delta_r, std::optional< double > control_error_delta_r_outward, std::optional< double > max_allowed_radial_distance, double dt_lambda_00, const ylm::Strahlkorper< Frame > &apparent_horizon, const ylm::Strahlkorper< Frame > &excision_boundary, const Scalar< DataVector > &lapse_on_excision_boundary, const tnsr::I< DataVector, 3, Frame > &frame_components_of_grid_shift, const tnsr::ii< DataVector, 3, Frame > &spatial_metric_on_excision_boundary, const tnsr::II< DataVector, 3, Frame > &inverse_spatial_metric_on_excision_boundary) 
Computes the size control error, updating the stored info. More...  
void  register_derived_with_charm () 
template<size_t DerivOrder, ::domain::ObjectLabel Horizon, typename Metavariables >  
void  update_averager (const gsl::not_null< Averager< DerivOrder  1 > * > averager, const gsl::not_null< ControlErrors::Size< DerivOrder, Horizon > * > control_error, const Parallel::GlobalCache< Metavariables > &cache, const double time, const DataVector ¤t_timescale, const std::string &function_of_time_name, const int current_measurement) 
Updates the Averager with information from the Size control error . More...  
template<size_t DerivOrder, ::domain::ObjectLabel Horizon, typename Metavariables >  
void  update_tuner (const gsl::not_null< TimescaleTuner< false > * > tuner, const gsl::not_null< ControlErrors::Size< DerivOrder, Horizon > * > control_error, const Parallel::GlobalCache< Metavariables > &cache, const double time, const std::string &function_of_time_name) 
Updates the TimescaleTuner with information from the Size control error . More...  
Variables  
template<typename T >  
constexpr bool  is_size_v = is_size<T>::value 
Check whether a control system is the control_system::Systems::Size system or not.  
Classes and functions used in implementation of size control.
void control_system::size::comoving_char_speed_derivative  (  gsl::not_null< Scalar< DataVector > * >  result, 
double  lambda_00,  
double  dt_lambda_00,  
double  horizon_00,  
double  dt_horizon_00,  
double  grid_frame_excision_sphere_radius,  
const tnsr::i< DataVector, 3, Frame::Distorted > &  excision_rhat,  
const tnsr::i< DataVector, 3, Frame::Distorted > &  excision_normal_one_form,  
const Scalar< DataVector > &  excision_normal_one_form_norm,  
const tnsr::I< DataVector, 3, Frame::Distorted > &  distorted_components_of_grid_shift,  
const tnsr::II< DataVector, 3, Frame::Distorted > &  inverse_spatial_metric_on_excision_boundary,  
const tnsr::Ijj< DataVector, 3, Frame::Distorted > &  spatial_christoffel_second_kind,  
const tnsr::i< DataVector, 3, Frame::Distorted > &  deriv_lapse,  
const tnsr::iJ< DataVector, 3, Frame::Distorted > &  deriv_of_distorted_shift,  
const InverseJacobian< DataVector, 3, Frame::Grid, Frame::Distorted > &  inverse_jacobian_grid_to_distorted  
) 
Computes the derivative of the comoving characteristic speed with respect to the size map parameter.
result  the derivative of the comoving char speed \(d v_c/d\lambda_{00}\), which is computed here using Eq. ( \(\ref{eq:result}\)). 
lambda_00  the map parameter \(\lambda_{00}\). This is the usual spherical harmonic coefficient, not a Spherepack value. 
dt_lambda_00  the time derivative of the map parameter 
horizon_00  the average coefficient of the horizon \(\hat{S}_{00}\). This is the usual spherical harmonic coefficient, not a Spherepack value. 
dt_horizon_00  the time derivative of horizon_00 
grid_frame_excision_sphere_radius  radius of the excision boundary in the grid frame, \(r_{\mathrm{EB}}\). 
excision_rhat  the direction cosine \(\xi_\hat{i}\). Not a spacetime tensor: it is raised/lowered with \(\delta_{ij}\) 
excision_normal_one_form  the unnormalized oneform \(\hat{s}_\hat{i}\) 
excision_normal_one_form_norm  the norm of the oneform \(a\) 
distorted_components_of_grid_shift  the quantity \(\beta^i \frac{\partial x^\hat{i}}{\partial x_i}\) evaluated on the excision boundary. This is not the shift in the distorted frame. 
inverse_spatial_metric_on_excision_boundary  metric in the distorted frame. 
spatial_christoffel_second_kind  the Christoffel symbols \(\Gamma^\hat{k}_{\hat{i}\hat{j}}\) 
deriv_lapse  the spatial derivative of the lapse \(\partial_\hat{i} \alpha\) 
deriv_of_distorted_shift  the spatial derivative of the shift in the distorted frame \(\partial_\hat{j} \hat{\beta}^\hat{i}\). This is not the derivative of distorted_components_of_grid_shift. 
inverse_jacobian_grid_to_distorted  the quantity \(J^i_\hat{k}=\partial_\hat{k} x^i\), where \(x^i\) are the grid frame coordinates and \(x^{\hat k}\) are the distorted frame coordinates. 
The characteristic speed on the excision boundary is
\begin{align} v &= \alpha + n_i\beta^i \end{align}
where \(\alpha\) is the lapse (invariant under frame transformations), \(\beta^i\) is the gridframe shift, and \(n_i\) is the metricnormalized outwardpointing (i.e. pointing out of the black hole, toward larger radius) normal oneform to the excision boundary in the grid frame. (Note that the usual expression for the characteristic speed, as in eq. 87 of [88], has a minus sign and defines \(n_i\) as the inwardpointing (i.e. out of the computational domain) normal; here we have a plus sign and we define \(n_i\) as outwardpointing because the outwardpointing normal is passed into comoving_char_speed_derivative.)
The size/shape map at the excision boundary is given by Eq. 72 of [88] :
\begin{align} \hat{x}^i &= \frac{x^i}{r_{\mathrm{EB}}} \left(1  \lambda_{00} Y_{00} \sum_{\ell>0} Y_{\ell m} \lambda_{\ell m}\right), \label{eq:map} \end{align}
where \(\hat{x}^i\) are the distortedframe coordinates and \(x^i\) are the gridframe coordinates, and where we have separated the \(\ell=0\) piece from the sum. Here \(Y_{\ell m}\) are spherical harmonics, \(\lambda_{\ell m}\) are the map parameters, and \(r_{\mathrm{EB}}\) is the radius of the excision boundary in the grid frame (where the excision boundary is a sphere). The final term with the sum over \(\ell>0\) is independent of \(\lambda_{00}\), and will not be important because below we will be differentiating the map with respect to \(\lambda_{00}\).
The comoving characteristic speed is given by rewriting Eq. 98 of [88] in terms of the distortedframe shift:
\begin{align} v_c &= \alpha +\hat{n}_\hat{i}\hat{\beta}^\hat{i}  Y_{00} \hat{n}_{\hat i} \xi^{\hat i} \left[ \dot{\hat{S}}_{00} (\lambda_{00}  r_{\mathrm{EB}}/Y_{00}) / \hat{S}_{00} + \frac{1}{Y_{00}} \sum_{\ell>0} Y_{\ell m} \dot{\lambda}_{\ell m} \right], \\ &= \alpha +\hat{n}_\hat{i}\beta^\hat{i}  Y_{00} \hat{n}_{\hat i} \xi^{\hat i} \left[ \dot{\hat{S}}_{00} (\lambda_{00}  r_{\mathrm{EB}}/Y_{00}) / \hat{S}_{00} \dot{\lambda}_{00} \right], \label{eq:comovingspeed} \end{align}
where in the last line we have rewritten \(\hat{\beta}^\hat{i}\) in terms of \(\beta^\hat{i}\) (see Eq. ( \(\ref{eq:framecompsshiftdef}\)) below) and we have substituted the time derivative of Eq. ( \(\ref{eq:map}\)). Here \(\dot{\lambda}_{00}\) is the time derivative of \(\lambda_{00}\), and \(\hat{S}_{00}\) is the constant sphericalharmonic coefficient of the horizon and \(\dot{\hat{S}}_{00}\) is its time derivative. The symbol \(\xi^{\hat i}\) is a direction cosine, i.e. \(x^i/r_{\mathrm{EB}}\) evaluated on the excision boundary, which is the same as \(\hat{x}^i/\hat{r}_{\mathrm{EB}}\) evaluated on the excision boundary because the size and shape maps preserve angles. Note that \(r_{\mathrm{EB}}\) is a constant but \(\hat{r}_{\mathrm{EB}}\) is a function of angles. Note also that \(\xi^{\hat i}\) is not a vector; it is a coordinate quantity. In particular, the lowerindex \(\xi_{\hat i}\) is \(\delta_{ij}x^j/r_{\mathrm{EB}}\). The nonvectorness of \(\xi^{\hat i}\) (and of \(x^i\) itself in Eq. ( \(\ref{eq:map}\))) might cause some confusion when using the Einstein summation convention; we attempt to alleviate that confusion by never using the lowerindex \(\xi_{\hat i}\) and by keeping \(\delta_{ij}\) in formulas below. The normal \(\hat{n}_\hat{i}\) is the same as \(n_i\) transformed into the distorted frame, that is \(\hat{n}_\hat{i} = n_j \partial x^j/\partial\hat{x}^\hat{i}\). We have put a hat on \(\hat{n}\) in addition to putting a hat on its index (despite the usual convention that tensors have decorations on indices and not on the tensors themselves) to reduce later ambiguities in notation that arise because Eq. ( \(\ref{eq:map}\)) has the same index on both sides of the equation and because \(\xi^{\hat i}\) and \(x^i\) are not tensors. The quantity \(\beta^\hat{i}\) in Eq. ( \(\ref{eq:comovingspeed}\)) is the distortedframe component of the gridframe shift, defined by
\begin{align} \beta^\hat{i} &= \beta^i \frac{\partial \hat{x}^\hat{i}}{\partial x^i}. \label{eq:shiftyquantity} \end{align}
This is not the shift in the distorted frame \(\hat{\beta}^\hat{i}\), because the shift does not transform like a spatial tensor under the maps.
If the comoving characteristic speed \(v_c\) is negative and remains negative forever, then size control will fail. Therefore \(v_c\) is used in making decisions in size control. We care about \(d v_c/d\lambda_{00}\) because the sign of that quantity tells us whether \(v_c\) will increase or decrease when we increase or decrease the map parameter \(\lambda_{00}\); this information will be used to decide whether to transition between different size control states.
This function computes \(d v_c/d\lambda_{00}\) on the excision boundary, where the total derivative means that all other map parameters (like \(\lambda_{\ell m}\) for \(\ell>0\)) are held fixed, and the coordinates of the excision boundary (the grid coordinates) are held fixed. We also hold fixed \(\dot{\lambda}_{00}\) because we are interested in how \(v_c\) changes from a configuration with a given \(\lambda_{00}\) and \(\dot{\lambda}_{00}\sim 0\) to another configuration with a different nearby \(\lambda_{00}\) and also with \(\dot{\lambda}_{00}\sim 0\).
Here we derive an expression for \(d v_c/d\lambda_{00}\). This expression will be complicated, mostly because of the normals \(\hat{n}_\hat{i}\) that appear in Eq. ( \(\ref{eq:comovingspeed}\)) and because of the Jacobians.
First, note that by differentiating Eq. ( \(\ref{eq:map}\)) we obtain
\begin{align} \frac{d\hat{x}^i}{d\lambda_{00}} &=  \frac{x^i Y_{00}}{r_{\mathrm{EB}}} \\ &= \xi^i Y_{00}, \end{align}
where the last line follows from the definition of the direction cosines.
The Jacobian of the map is
\begin{align} \frac{\partial \hat{x}^i}{\partial x^j} &= (1  \lambda_{00} Y_{00}/r_{\mathrm{EB}} + B) \delta^i_j + x^i \frac{\partial B}{\partial x^j}, \end{align}
where \(B\) represents the term with the sum over \(\ell>0\) in Eq. ( \(\ref{eq:map}\)); this term is independent of \(\lambda_{00}\). Therefore, we have
\begin{align} \frac{d}{d\lambda_{00}}\frac{\partial \hat{x}^i}{\partial x^j} &= \frac{Y_{00}}{r_{\mathrm{EB}}} \delta^i_j. \label{eq:derivjacobian} \end{align}
But we want the derivative of the inverse Jacobian, not the forward Jacobian. By taking the derivative of the identity
\begin{align} \frac{\partial \hat{x}^\hat{i}}{\partial x^k} \frac{\partial x^k}{\partial \hat{x}^\hat{j}} &= \delta^\hat{i}_\hat{j} \end{align}
and by using Eq. ( \(\ref{eq:derivjacobian}\)) we can derive
\begin{align} \frac{d}{d\lambda_{00}}\frac{\partial x^i}{\partial \hat{x}^j} &= +\frac{Y_{00}}{r_{\mathrm{EB}}} \frac{\partial x^i}{\partial \hat{x}^k} \frac{\partial x^k}{\partial \hat{x}^j}. \label{eq:strangederivjacobian} \end{align}
Note that the righthand side of Eq. ( \(\ref{eq:strangederivjacobian}\)) has two inverse Jacobians contracted with each other, which is not the same as \(\delta^i_j\).
Assume we have an arbitrary function of space \(f(\hat{x}^i)\). Here we treat \(f\) as a function of the distortedframe coordinates \(\hat{x}^i\) and not a function of the gridframe coordinates. This is because we consider the metric functions to be defined in the inertial frame (and equivalently for our purposes the functions are defined in the distorted frame because the distortedtoinertial map is independent of \(\lambda_{00}\)), and we consider \(\lambda_{00}\) a parameter in a map that moves the grid with respect to these distortedframe metric functions. The derivative of \(f\) can be written
\begin{align} \frac{d}{d\lambda_{00}}f &= \frac{\partial f}{\partial \hat{x}^i} \frac{d \hat{x}^i}{d\lambda_{00}}\\ &= \xi^\hat{i} Y_{00} \frac{\partial f}{\partial \hat{x}^i}. \label{eq:derivf} \end{align}
This is how we will evaluate derivatives of metric functions like the lapse.
To differentiate the quantity defined by Eq. ( \(\ref{eq:shiftyquantity}\)) note that
\begin{align} \beta^\hat{i} &= \beta^i \frac{\partial \hat{x}^\hat{i}}{\partial x^i} \\ &= \hat{\beta}^\hat{i} + \frac{\partial \hat{x}^\hat{i}}{\partial t}, \label{eq:framecompsshiftdef} \end{align}
where \(\hat{\beta}^\hat{i} \equiv \alpha^2 g^{\hat{0}\hat{i}}\) is the shift in the distorted frame. From the map, Eq. ( \(\ref{eq:map}\)), we see that
\begin{align} \frac{d}{d\lambda_{00}} \frac{\partial \hat{x}^\hat{i}}{\partial t} &=0, \end{align}
because there is no remaining \(\lambda_{00}\) in \(\frac{\partial \hat{x}^\hat{i}}{\partial t}\). So
\begin{align} \frac{d}{d\lambda_{00}}\beta^\hat{i} &= \frac{d}{d\lambda_{00}} \hat{\beta}^\hat{i} \\ &= \xi^\hat{j} Y_{00} \partial_\hat{j} \hat{\beta}^\hat{i}, \end{align}
where we have used Eq. ( \(\ref{eq:derivf}\)) in the last line. Note that we cannot use Eq. ( \(\ref{eq:derivf}\)) on \(\beta^\hat{i}\) directly, because \(\beta^\hat{i}\) depends in a complicated way on the gridtodistorted map. In particular, we will be evaluating \(\partial_\hat{j} \hat{\beta}^\hat{i}\) numerically, and numerical spatial derivatives \(\partial_\hat{j} \hat{\beta}^\hat{i}\) are not the same as numerical spatial derivatives \(\partial_\hat{j} \beta^\hat{i}\).
The normal to the surface is the most complicated expression in Eq. ( \(\ref{eq:comovingspeed}\)), because of how it depends on the map and on the metric. The gridframe unnormalized outwardpointing oneform to the excision boundary is
\begin{align} s_i &= \xi^j \delta_{ij}, \end{align}
because the excision boundary is a sphere of fixed radius in the grid frame. Therefore \(s_i\) doesn't depend on \(\lambda_{00}\).
The normalized oneform \(\hat{n}_\hat{i}\) is given by
\begin{align} \hat{n}_\hat{i} &= \frac{\hat{s}_{\hat i}}{a}, \end{align}
where
\begin{align} \hat{s}_{\hat i} &= s_i \frac{\partial x^i}{\partial \hat{x}^{\hat i}},\\ a^2 &= \hat{s}_{\hat i} \hat{s}_{\hat j} \gamma^{\hat{i} \hat{j}}. \end{align}
Here \(\gamma^{\hat{i} \hat{j}}\) is the inverse 3metric in the distorted frame. Again, to avoid ambiguity later, we have put hats on \(n\) and \(s\), despite the usual convention that when transforming tensors one puts hats on the indices and not on the tensors.
Now
\begin{align} \frac{d}{d\lambda_{00}} \hat{s}_{\hat i} &= \frac{Y_{00}}{r_{\mathrm{EB}}} \hat{s}_k\frac{\partial x^k}{\partial \hat{x}^\hat{i}}, \\ \frac{d}{d\lambda_{00}} a^2 &= 2 \frac{Y_{00}}{r_{\mathrm{EB}}} \hat{s}_k\frac{\partial x^k}{\partial \hat{x}^\hat{i}} \hat{s}_{\hat j} \gamma^{\hat{i} \hat{j}} + \hat{s}_{\hat i} \hat{s}_{\hat j} \gamma^{\hat{i} \hat{k}} \gamma^{\hat{j} \hat{l}} \xi^\hat{m} Y_{00} \partial_{\hat m} \gamma_{\hat{k} \hat{l}}. \end{align}
Here we have used Eq. ( \(\ref{eq:strangederivjacobian}\)) to differentiate the Jacobian, and Eq. ( \(\ref{eq:derivf}\)) to differentiate the 3metric. We have also refrained from raising and lowering indices on \(\hat{n}_\hat{i}\), \(\hat{s}_\hat{i}\), and \(\xi^\hat{i}\) to alleviate potential confusion over whether to raise or lower using \(\gamma_{\hat{i} \hat{j}}\) or using \(\delta_{\hat{i}\hat{j}}\). The factor \(\hat{s}_k \partial x^k/\partial \hat{x}^\hat{i}\) is unusal and is not a tensor ( \(\hat{s}_k\) is a tensor but the Jacobian it is being multiplied by is the inverse of the one that would transform it into a different frame); this factor arises because some quantities being differentiated are not tensors.
Given the above, the derivative of the normalized normal oneform is
\begin{align} \frac{d}{d\lambda_{00}} \hat{n}_{\hat i} &= \frac{1}{a}\frac{d}{d\lambda_{00}} \hat{s}_{\hat i}  \hat{s}_{\hat i} \frac{1}{2a^3} \frac{d}{d\lambda_{00}} a^2\\ &= \hat{s}_i\frac{Y_{00}}{a r_{\mathrm{EB}}} \frac{\partial x^i}{\partial \hat{x}^\hat{i}}  \hat{s}_{\hat i} \frac{1}{a^3} \hat{s}_i\frac{Y_{00}}{r_{\mathrm{EB}}} \frac{\partial x^i}{\partial \hat{x}^\hat{k}} \hat{s}_{\hat j} \gamma^{\hat{k} \hat{j}}  \hat{s}_{\hat i} \frac{Y_{00}}{2a^3} \hat{s}_{\hat p} \hat{s}_{\hat j} \gamma^{\hat{p} \hat{k}} \gamma^{\hat{j} \hat{l}} \xi^\hat{m} \partial_{\hat m} \gamma_{\hat{k} \hat{l}} \\ &= \hat{n}_i \frac{\partial x^i}{\partial \hat{x}^\hat{k}} \frac{Y_{00}}{r_{\mathrm{EB}}} (\delta^\hat{k}_\hat{i}  \hat{n}^\hat{k} \hat{n}_\hat{i})  \hat{s}_{\hat i} \frac{Y_{00}}{2a^3} \hat{s}_{\hat p} \hat{s}_{\hat j} \gamma^{\hat{p} \hat{k}} \gamma^{\hat{j} \hat{l}} \xi^\hat{m} \partial_{\hat m} \gamma_{\hat{k} \hat{l}} \label{eq:dnormal} \\ &= \hat{n}_i \frac{\partial x^i}{\partial \hat{x}^\hat{k}} \frac{Y_{00}}{r_{\mathrm{EB}}} (\delta^\hat{k}_\hat{i}  \hat{n}^\hat{k} \hat{n}_\hat{i})  Y_{00} \hat{n}_{\hat i} \hat{n}_{\hat p} \hat{n}_{\hat j} \gamma^{\hat{p} \hat{k}} \xi^\hat{m} \Gamma^\hat{j}_{\hat{k} \hat{m}} \label{eq:dnormalgamma}, \end{align}
where we have eliminated \(\hat{s}_{\hat i}\) and \(a\) in favor of \(\hat{n}_{\hat i}\) and we have substituted 3Christoffel symbols for spatial derivatives of the 3metric (and the factor of 2 on the penultimate line has been absorbed into the 3Christoffel symbol on the last line). Note that the last term in Eq. ( \(\ref{eq:dnormalgamma}\)) could also be derived by differentiating \(\hat{n}_\hat{i}\hat{n}_\hat{j}\gamma^{\hat{i}\hat{j}}=1\). The first term in Eq. ( \(\ref{eq:dnormalgamma}\)) is strange because the inverse Jacobian (as opposed to the forward Jacobian) is contracted with \(\hat{n}_i\), so that is not a tensor transformation.
We can now differentiate Eq. ( \(\ref{eq:comovingspeed}\)) to obtain
\begin{align} \frac{d}{d\lambda_{00}} v_c &= \xi^\hat{i} Y_{00} \partial_\hat{i} \alpha +\left[ \beta^\hat{i}  Y_{00} \xi^\hat{i} \dot{\hat{S}}_{00} (\lambda_{00}  r_{\mathrm{EB}}/Y_{00}) / \hat{S}_{00} + Y_{00} \xi^\hat{i}\dot{\lambda}_{00} \right] \frac{d}{d\lambda_{00}} \hat{n}_{\hat i} \nonumber \\ & \hat{n}_{\hat i} \xi^\hat{j} Y_{00} \partial_\hat{j} \hat{\beta}^\hat{i}  Y_{00} \hat{n}_{\hat i} \xi^{\hat i} \dot{\hat{S}}_{00}/\hat{S}_{00}, \label{eq:result} \end{align}
where \(\frac{d}{d\lambda_{00}} \hat{n}_{\hat i}\) is given by Eq. ( \(\ref{eq:dnormalgamma}\)).
ErrorDiagnostics control_system::size::control_error  (  const gsl::not_null< Info * >  info, 
const gsl::not_null< intrp::ZeroCrossingPredictor * >  predictor_char_speed,  
const gsl::not_null< intrp::ZeroCrossingPredictor * >  predictor_comoving_char_speed,  
const gsl::not_null< intrp::ZeroCrossingPredictor * >  predictor_delta_radius,  
double  time,  
double  control_error_delta_r,  
std::optional< double >  control_error_delta_r_outward,  
std::optional< double >  max_allowed_radial_distance,  
double  dt_lambda_00,  
const ylm::Strahlkorper< Frame > &  apparent_horizon,  
const ylm::Strahlkorper< Frame > &  excision_boundary,  
const Scalar< DataVector > &  lapse_on_excision_boundary,  
const tnsr::I< DataVector, 3, Frame > &  frame_components_of_grid_shift,  
const tnsr::ii< DataVector, 3, Frame > &  spatial_metric_on_excision_boundary,  
const tnsr::II< DataVector, 3, Frame > &  inverse_spatial_metric_on_excision_boundary  
) 
Computes the size control error, updating the stored info.
Frame  should be Frame::Distorted if Frame::Distorted exists. 
info  struct containing parameters that will be used/filled. Some of the fields in info will guide the behavior of other control system components like the averager and (possibly) the time step. 
predictor_char_speed  ZeroCrossingPredictor for the characteristic speed. 
predictor_comoving_char_speed  ZeroCrossingPredictor for the comoving characteristic speed. 
predictor_delta_radius  ZeroCrossingPredictor for the difference in radius between the horizon and the excision boundary. 
time  the current time. 
control_error_delta_r  the control error for the DeltaR state. This is used in other states as well. 
control_error_delta_r_outward  the control error for the DeltaRDriftOutward state. If std::nullopt, then DeltaRDriftOutward will not be used. 
max_allowed_radial_distance  the maximum average radial distance between the horizon and the excision boundary that is allowed without triggering the DeltaRDriftOutward state. If std::nullopt, then DeltaRDriftOutward will not be used. 
dt_lambda_00  the time derivative of the map parameter lambda_00 
apparent_horizon  the current horizon in frame Frame. 
excision_boundary  a Strahlkorper representing the excision boundary in frame Frame. Note that the excision boundary is assumed to be a sphere in the grid frame. 
lapse_on_excision_boundary  Lapse on the excision boundary. 
frame_components_of_grid_shift  The quantity \(\beta^i \frac{\partial x^\hat{i}}{\partial x_i}\) (see below) evaluated on the excision boundary. This is a tensor in frame Frame. 
spatial_metric_on_excision_boundary  metric in frame Frame. 
inverse_spatial_metric_on_excision_boundary  metric in frame Frame. 
Returns: Returns an ErrorDiagnostics
object which, in addition to the actual control error, holds a lot of diagnostic information about how the control error was calculated. This information could be used to print to a file if desired.
The characteristic speed that is needed here is
\begin{align} v &= \alpha n_i\beta^i \\ v &= \alpha n_\hat{i}\hat{\beta}^\hat{i}  n_\hat{i}\frac{\partial x^\hat{i}}{\partial t} \\ v &= \alpha n_\bar{i}\bar{\beta}^\bar{i}  n_\bar{i}\frac{\partial x^\bar{i}}{\partial t} \\ v &= \alpha  n_\hat{i} \frac{\partial x^\hat{i}}{\partial x^i} \beta^i, \end{align}
where we have written many equivalent forms in terms of quantities defined in different frames.
Here \(\alpha\) is the lapse, which is invariant under frame transformations, \(n_i\), \(n_\hat{i}\), and \(n_\bar{i}\) are the metricnormalized normal oneform to the Strahlkorper in the grid, distorted, and inertial frames, and \(\beta^i\), \(\hat{\beta}^\hat{i}\), and \(\bar{\beta}^\bar{i}\) are the shift in the grid, distorted, and inertial frames.
Note that we decorate the shift with hats and bars in addition to decorating its index, because the shift transforms in a nonobvious way under frame transformations so it is easy to make mistakes. To be clear, these different shifts are defined by
\begin{align} \beta^i &= \alpha^2 g^{0i},\\ \hat{\beta}^\hat{i} &= \alpha^2 g^{\hat{0}\hat{i}},\\ \bar{\beta}^\bar{i} &= \alpha^2 g^{\bar{0}\bar{i}}, \end{align}
where \(g^{ab}\) is the spacetime metric, and they transform like
\begin{align} \hat{\beta}^\hat{i} &= \beta^i \frac{\partial x^\hat{i}}{\partial x^i} \frac{\partial x^\hat{i}}{\partial t}. \end{align}
The quantity we pass as frame_components_of_grid_shift is
\begin{align} \beta^i \frac{\partial x^\hat{i}}{\partial x^i} &= \hat{\beta}^\hat{i} + \frac{\partial x^\hat{i}}{\partial t} \\ &= \bar{\beta}^\bar{j}\frac{\partial x^\hat{i}}{\partial x^i} \frac{\partial x^i}{\partial x^\bar{j}} + \frac{\partial x^\hat{i}}{\partial x^\bar{j}} \frac{\partial x^\bar{j}}{\partial t}, \end{align}
where we have listed several equivalent formulas that involve quantities in different frames.
double control_system::size::control_error_delta_r  (  const double  horizon_00, 
const double  dt_horizon_00,  
const double  lambda_00,  
const double  dt_lambda_00,  
const double  grid_frame_excision_sphere_radius  
) 
Function that computes the control error for control_system::size::States::DeltaR
.
This is helpful to have calculated separately because other control errors may make use of this quantity. The equation for the control error is given in Eq. 96 in [88].
horizon_00  The \(l=0,m=0\) coefficient of the apparent horizon in the distorted frame. 
dt_horizon_00  The \(l=0,m=0\) coefficient of the time derivative of the apparent horizon in the distorted frame, where the derivative is taken in the distorted frame as well. 
lambda_00  The \(l=0,m=0\) component of the function of time for the time dependent map 
dt_lambda_00  The \(l=0,m=0\) component of the time derivative of the function of time for the time dependent map 
grid_frame_excision_sphere_radius  Radius of the excision sphere in the grid frame 
void control_system::size::update_averager  (  const gsl::not_null< Averager< DerivOrder  1 > * >  averager, 
const gsl::not_null< ControlErrors::Size< DerivOrder, Horizon > * >  control_error,  
const Parallel::GlobalCache< Metavariables > &  cache,  
const double  time,  
const DataVector &  current_timescale,  
const std::string &  function_of_time_name,  
const int  current_measurement  
) 
Updates the Averager with information from the Size control error .
After we calculate the control error, we check if a discontinuous change has occurred (the internal control_system::size::State
changed). If no discontinuous change has occurred, then we do nothing. If one did occur, we get a history of control errors from the Size control error and use that to repopulate the Averager history.
control_system::Tags::Averager
for why the Averager is templated on DerivOrder  1
. void control_system::size::update_tuner  (  const gsl::not_null< TimescaleTuner< false > * >  tuner, 
const gsl::not_null< ControlErrors::Size< DerivOrder, Horizon > * >  control_error,  
const Parallel::GlobalCache< Metavariables > &  cache,  
const double  time,  
const std::string &  function_of_time_name  
) 
Updates the TimescaleTuner with information from the Size control error .
We check for a suggested timescale from the Size control error . If one is suggested and it is smaller than the current damping timescale, we set the timescale in the TimescaleTuner to this suggested value. Otherwise, we let the TimescaleTuner adjust the timescale. Regardless of whether a timescale was suggested or not, we always reset the size control error.