SpECTRE  v2026.04.01
Loading...
Searching...
No Matches
evolution::Ringdown Namespace Reference

Functionality for evolving a ringdown following a compact-binary merger. More...

Functions

double minimum_ahc_excision_radius (const std::string &path_to_volume_data, const std::string &volume_subfile_name, const std::string &path_to_horizons_h5, const std::string &surface_subfile_name, const std::string &path_to_AhC_distorted_h5, const std::vector< std::string > &AhC_distorted_subfile_names, double match_time, double settling_timescale, double excision_A_radius, double excision_B_radius, std::array< double, 3 > excision_A_center, std::array< double, 3 > excision_B_center, const std::optional< std::array< double, 3 > > &exp_func_and_2_derivs=std::nullopt, const std::optional< std::array< double, 3 > > &exp_outer_bdry_func_and_2_derivs=std::nullopt, const std::optional< std::vector< std::array< double, 4 > > > &rot_func_and_2_derivs=std::nullopt, const std::optional< std::array< std::array< double, 3 >, 3 > > &trans_func_and_2_derivs=std::nullopt, double match_time_tol=1e-12)
 This function finds a safe ringdown excision radius for starting the ringdown of a common horizon from a binary inspiral. It does this by finding a radius that will enclose every point on strahlkorpers that represent excisions A/B from the inspiral at the match time. It does this by taking excisions A/B from the inertial frame and transforming them to the ringdown grid frame. It iterates over all the points from excisions A/B in the ringdown-grid-frame until it finds the point that's the farthest from the geometric center of the ringdown excision. This is now the minimum radius we can choose to enclose the excisions A/B from the inspiral. This is not the ideal radius however, we then choose a radius that's 3/4 of the way between the radius of the common horizon at the match time and the minimum radius that encloses excisions A/B from the inspiral and check for multiple l_max values of excisions A/B to ensure they fit and the ringdown can start.
std::pair< std::vector< DataVector >, std::vector< std::array< double, 3 > > > strahlkorper_coefs_and_centers (const std::string &path_to_volume_data, const std::string &volume_subfile_name, const std::string &path_to_horizons_h5, const std::string &surface_subfile_name, size_t requested_number_of_times_from_end, double match_time, double settling_timescale, const std::optional< std::array< double, 3 > > &exp_func_and_2_derivs=std::nullopt, const std::optional< std::array< double, 3 > > &exp_outer_bdry_func_and_2_derivs=std::nullopt, const std::optional< std::vector< std::array< double, 4 > > > &rot_func_and_2_derivs=std::nullopt, const std::optional< std::array< std::array< double, 3 >, 3 > > &trans_func_and_2_derivs=std::nullopt)
 This function is used to transition from inspiral to ringdown. It reads inertial frame common horizon Strahlkorper coefs from a file and returns the Strahlkorper's temporary frame coefs and the inertial frame geometric centers at multiple times which will be used to initialize the shape and translation function of time for the ringdown.

Variables

constexpr double expansion_center_tolerance = 1e-8

Detailed Description

Functionality for evolving a ringdown following a compact-binary merger.

Function Documentation

◆ minimum_ahc_excision_radius()

double evolution::Ringdown::minimum_ahc_excision_radius ( const std::string & path_to_volume_data,
const std::string & volume_subfile_name,
const std::string & path_to_horizons_h5,
const std::string & surface_subfile_name,
const std::string & path_to_AhC_distorted_h5,
const std::vector< std::string > & AhC_distorted_subfile_names,
double match_time,
double settling_timescale,
double excision_A_radius,
double excision_B_radius,
std::array< double, 3 > excision_A_center,
std::array< double, 3 > excision_B_center,
const std::optional< std::array< double, 3 > > & exp_func_and_2_derivs = std::nullopt,
const std::optional< std::array< double, 3 > > & exp_outer_bdry_func_and_2_derivs = std::nullopt,
const std::optional< std::vector< std::array< double, 4 > > > & rot_func_and_2_derivs = std::nullopt,
const std::optional< std::array< std::array< double, 3 >, 3 > > & trans_func_and_2_derivs = std::nullopt,
double match_time_tol = 1e-12 )

This function finds a safe ringdown excision radius for starting the ringdown of a common horizon from a binary inspiral. It does this by finding a radius that will enclose every point on strahlkorpers that represent excisions A/B from the inspiral at the match time. It does this by taking excisions A/B from the inertial frame and transforming them to the ringdown grid frame. It iterates over all the points from excisions A/B in the ringdown-grid-frame until it finds the point that's the farthest from the geometric center of the ringdown excision. This is now the minimum radius we can choose to enclose the excisions A/B from the inspiral. This is not the ideal radius however, we then choose a radius that's 3/4 of the way between the radius of the common horizon at the match time and the minimum radius that encloses excisions A/B from the inspiral and check for multiple l_max values of excisions A/B to ensure they fit and the ringdown can start.

Details

It does this by constructing inspiral-grid-frame AhA/AhB excision strahlkorpers from the radii and centers passed to this function. It then maps those excisions to the inertial-frame using the inspiral domain and functions of time from the inspiral volume data and subfile supplied. We then construct a test ringdown domain that has all the corrected functions of time from ComputeRingdownShapeAndTranslationFoT.py and an initial guess for the inner radius. More details are outlined below.

Parameters
path_to_volume_dataThe full path to the volume data containing the domain and functions of time
volume_subfile_nameSubfile containing volume data output from the inspiral
path_to_horizons_h5Path to h5 file containing horizon data for AhA/B
surface_subfile_nameSubfile containing horizon data for AhA/B
path_to_AhC_distorted_h5Path to h5 file containing ringdown shape coefficients computed using ComputeRingdownShapeAndTranslationFoT.py
AhC_distorted_subfile_namesSubfiles in the h5 file containing shape coefficients
match_timeThe time to match the functions of time
settling_timescaleTimescale at which the functions of time settle to constant values
excision_A_radiusThe radius of excision A from the inspiral grid frame
excision_B_radiusThe radius of excision B from the inspiral grid frame
excision_A_centerThe center of excision A from the inspiral grid frame
excision_B_centerThe center of excision B from the inspiral grid frame
exp_func_and_2_derivsExpansion function of time from the inspiral
exp_outer_bdry_func_and_2_derivsOuter boundary expansion function of time from the inspiral
rot_func_and_2_derivsRotation function of time from the inspiral
trans_func_and_2_derivsThe corrected translation function of time computed by ComputeRingdownShapeAndTranslationFoT.py
match_time_tolThe difference allowed between the match time requested and the time found in h5 files

Using the corrected functions of time and our initial guess for the ringdown inner radius (the excision radius), excisions A/B are transformed from the inertial frame to the ringdown grid frame. The inner radius is iterated upon using 2 main loops, the outer loop which changes the L_max of the excisions A/B being transformed from the inspiral and the inner loop that changes the excision radius used in the ringdown. The general flow for these loops is as follows:

Let \(ahc\_average\_radius\) be the average radius of the common horizon in the inertial frame and since have strahlkorper data from the inertial frame AhC we set \(ahc\_average\_radius\) so that lambda00=0 at the match time.

Let \(ringdown\_excision\_radius\) be the radius of (spherical) excision boundary in ringdown grid frame.

Let \(ringdown\_excision\_factor\) be the factor we multiply the \(ahc\_average\_radius\) by to get the \(ringdown\_excision\_radius\).

The goal is to find a good \(ringdown\_excision\_factor\)

1) Choose an initial guess for the \(ringdown\_excision\_factor\). We choose this to be 0.94 by default.

2) Choose an initial guess for current_l_max, the angular resolution of spherical Strahlkorpers that match excision A and B (not horizons) in the inspiral grid frame. We choose current_l_max=20 intially.

3) Construct Strahlkorpers in the Inspiral grid frame that correspond to excisions A/B, the excision regions (not the horizons) of the two individual holes. These are spherical in the inspiral grid frame, and have L=current_l_max.

4) Map the Strahlkorper excisions A/B to the inertial frame. Now they are not spherical.

4a) Using the current \(ringdown\_excision\_factor\), construct a test domain to map excisions A/B from the inertial frame to the ringdown grid frame. This domain's functions of time should contain the scaling and rotation functions of time from the inspiral that settle to const and the shape and corrected translation function of time output by ComputeRingdownShapeAndTranslationFoT.py

4b) Map the Strahlkorper excisions A/B to the Ringdown grid frame. They are still not spherical.

4c) Loop through all the points on Ringdown grid excisions A/B, and find the point that is the maximum distance from the origin. Call that maximum distance \(min\_excision\_radius\).

4d) A Ringdown grid sphere of radius \(min\_excision\_radius\) centered at the origin will (barely) enclose both excisions A/B, so choose \(minimum\_ringdown\_excision\_factor = \frac{min\_excision\_radius} {ahc\_average\_radius}\) as the minimum possible \(ringdown\_excision\_factor\). And then choose the new value of \(ringdown\_excision\_factor\) to be

\begin{equation}ringdown\_excision\_factor=1-0.25*(1-minimum\_ringdown\_excision\_factor) \end{equation}

Which puts the excision radius 3/4 of the way between the \(ahc\_average\_radius\) and the \(min\_excision\_radius\)

4e) If this is the first inner iteration, or if \(|ringdown\_excision\_factor-previous\_ringdown\_excision\_factor|>eps\), then set \(previous\_ringdown\_excision\_factor=ringdown\_excision\_factor\) and goto 3a, where 3a is repeated using the new \(ringdown\_excision\_factor\). We choose \(eps = \frac{10^{-3}}{q}\) where q is an approximation of the mass ratio. The reason this is iterative is because the new \(ringdown\_excision\_factor\) in 3d depends on the ringdown_excision_factor used when constructing the test domain.

5) If we get here, then inner iteration has converged. But that iteration depends on the \(current\_l\_max\) used to construct excisions A/B in step 2. If this is the first outer iteration, or if \(|ringdown\_excision\_factor-previous\_ringdown\_excision\_factor|>eps\), then set \(previous\_ringdown\_excision\_factor=ringdown\_excision\_factor\), and increment \(current\_l\_max\) by some increment (which we choose to be 6), and go back to 2.

6) If we get here, the outer iteration is converged and now we have a final \(ringdown\_excision\_factor\).

Note
This implementation does not do everything SpEC does yet, it is currently missing rescaling the shape coefficients held in 'path_to_AhC_distorted_h5' by \(excision\_radius / average\_ahc\_radius\) every time it constructs a test ringdown domain. This step helps the shape of the excision match the shape of the apparent horizon.

◆ strahlkorper_coefs_and_centers()

std::pair< std::vector< DataVector >, std::vector< std::array< double, 3 > > > evolution::Ringdown::strahlkorper_coefs_and_centers ( const std::string & path_to_volume_data,
const std::string & volume_subfile_name,
const std::string & path_to_horizons_h5,
const std::string & surface_subfile_name,
size_t requested_number_of_times_from_end,
double match_time,
double settling_timescale,
const std::optional< std::array< double, 3 > > & exp_func_and_2_derivs = std::nullopt,
const std::optional< std::array< double, 3 > > & exp_outer_bdry_func_and_2_derivs = std::nullopt,
const std::optional< std::vector< std::array< double, 4 > > > & rot_func_and_2_derivs = std::nullopt,
const std::optional< std::array< std::array< double, 3 >, 3 > > & trans_func_and_2_derivs = std::nullopt )

This function is used to transition from inspiral to ringdown. It reads inertial frame common horizon Strahlkorper coefs from a file and returns the Strahlkorper's temporary frame coefs and the inertial frame geometric centers at multiple times which will be used to initialize the shape and translation function of time for the ringdown.

Details

Reads common horizon Strahlkorpers (assumed to be in the inertial frame) from a file, then transforms them to a temporary ringdown domain defined by the expansion, rotation, and translation maps from the inspiral specified by exp_func_and_2_derivs, exp_outer_bdry_func_and_2_derivs, rot_func_and_2_derivs, and trans_func_and_2_derivs. The expansion and rotation functions of time from the inspiral are the same as the ringdown frame's expansion and rotation maps at the given match_time, but later settle to constant values by the given settling_timescale. The translation function of time supplied from the inspiral is not the translation map we'll use in the final ringdown, it is only used to correctly map the common horizon's geometric center so that we can make the corrected translation map for the final ringdown. How to correct the translation map is explained in detail below. A shape map is not specified, because we do not yet know the shape coefficients of the common horizon for the ringdown. There are 4 frames we transition between to find the shape coefficients and correct the translation map. The frames are as follows:

\(\textbf{Inertial frame}\): This is the same for ringdown and inspiral, by definition. It's the frame where we measure the waveforms, and it's the frame in which we define the tensor components (e.g. the 'x' and 'y' in 'g_xy').

\(\textbf{Ringdown Grid Frame}\): This is the frame where the ringdown excision boundary is spherical and where the ringdown grid lives.

\(\textbf{Temporary frame}\): The inertial frame pushed through the inverse translation-rotation-expansion map, where "translation" is the inspiral's translation map, and "rotation" and "expansion" are new rotation and expansion maps that match the inspiral's rotation and expansion at the outer boundary at the match time, have some smooth falloff in the interior, and have a "settle to constant" time dependence. This frame is almost the ringdown distorted frame, except for an uncorrected translation map which is explained in detail below.

\(\textbf{Ringdown distorted frame}\): This is the ringdown grid frame pushed through the (final) forward distortion map. Or equivalently, this is the inertial frame pushed through the inverse translation-rotation-expansion map, where here "translation" means the final corrected translation map, not the inspiral's translation map, and "rotation" and "expansion" are the same as in the temporary frame.

We get the shape coefficients by transforming the common horizon to the temporary frame which is almost the ringdown distorted frame except for the uncorrected translation map. The translation map is corrected by transforming the common horizon from the temporary frame to the inertial frame and saving the geometric center points at multiple times. We then take those geometric center points and build the corrected translation function of time. This is done because the center of the Strahlkorper in this temporary frame is NOT the origin (this is the case whether or not you say Recenter=true when transforming the Strahlkorper), but the distortion map does its distortion about the origin. Possible ways to account for this:

1) Put a translation map before the distortion map.

2) Change the center of the distortion map. (then we need to live with this during the ringdown).

3) Correct the current translation map so that the excision boundary maps to the correct place.

We choose 3). Section 6 of [100] explains in more detail of how we initialize the shape/translation map, but idea is that in Eq. (104), the horizon can be written as

\begin{equation}x^{\bar{i}}_{AH} = x^{\bar{i}}_{AHc} + n^{\bar{i}} \sum_{lm}S_{lm} Y_{lm}(\theta,\phi) \end{equation}

where \(x^{\bar{i}}_{AH}\) is the common horizon Strahklorper in the temporary frame, \(x^{\bar{i}}_{AHc}\) is the expansion center of the Strahlkorper in the temporary frame, which is time-dependent and not zero, \(n^{\bar{i}}\) is the direction unit vector in the ( \(\theta,\phi\)) direction relative to \(x^{\bar{i}}_{AHc}\), \(\bar{i}\) is the index corresponding to the temporary frame, and \(S_{lm}\) are the Strahlkorper coefficients. Now,

\begin{equation}x^i = T0^i + M^i_{\bar{i}} x^{\bar{i}} \end{equation}

where \(T0^i\) is the inspiral translation map, and \(M^i_{\bar{i}}\) is scaling+rotation. Thus,

\begin{equation}x^i_AH = T0^i + M^i_{\bar{i}} x^{\bar{i}}_{AH} = T0^i + M^i_{\bar{i}} x^{\bar{i}}_{AHc} + M^i_{\bar{i}} n^{\bar{i}} \sum_{lm} S_{lm} Y_{lm} \end{equation}

Therefore if you define a new translation map \(T^i\) as in Eq. (107) (corrected translation map that will be used in the final ringdown) \(T^i = T0^i + M^i_{\bar{i}} x^{\bar{i}}_{AHc}\) (that is, you define \(T^i\) to be the same as \(x^i_{AHc}\)), then you can rewrite the relationship as

\begin{equation}x^{i}_{AH} = T^i + M^i_{\bar{i}} \sum_{lm} S_{lm} Y_{lm} n^{\bar{i}} \end{equation}

Therefore we use a new map \(x^i = T^i + M^i_{\bar{i}} x^{\tilde{i}}\) where \(\tilde{i}\) refers to the final ringdown distorted frame, \(x^{\tilde{i}}\) is a new coordinate where \(x^{\tilde{i}}_{AHc} = 0\) and the coefficients of the AH in the \(x^{\tilde{i}}\) frame can be used unchanged (except for a minus sign) in the distortion map that connects \(x^{i_{grid}}\) and \(x^{\tilde{i}}\). This new map for \(x^i\) ensures that the excision boundary is mapped to the correct position.

Note
Only temporary frame common horizon coefs and inertial frame geometric center points within requested_number_of_times_from_end times from the final time are returned. The functions of time are computed by ComputeRingdownShapeAndTranslationFoT.py using the output from this function