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 <string>
9 : #include <vector>
10 :
11 : #include "DataStructures/DataVector.hpp"
12 : #include "NumericalAlgorithms/Strahlkorper/Strahlkorper.hpp"
13 :
14 1 : namespace evolution::Ringdown {
15 :
16 : /*!
17 : * \brief This function finds a safe ringdown excision radius for starting
18 : * the ringdown of a common horizon from a binary inspiral. It does this by
19 : * finding a radius that will enclose every point on strahlkorpers that
20 : * represent excisions A/B from the inspiral at the match time. It does this by
21 : * taking excisions A/B from the inertial frame and transforming them to the
22 : * ringdown grid frame. It iterates over all the points from excisions A/B in
23 : * the ringdown-grid-frame until it finds the point that's the farthest from the
24 : * geometric center of the ringdown excision. This is now the minimum radius we
25 : * can choose to enclose the excisions A/B from the inspiral. This is not the
26 : * ideal radius however, we then choose a radius that's 3/4 of the way between
27 : * the radius of the common horizon at the match time and the minimum radius
28 : * that encloses excisions A/B from the inspiral and check for multiple l_max
29 : * values of excisions A/B to ensure they fit and the ringdown can start.
30 :
31 : * \details It does this by constructing inspiral-grid-frame AhA/AhB excision
32 : * strahlkorpers from the radii and centers passed to this function. It then
33 : * maps those excisions to the inertial-frame using the inspiral domain
34 : * and functions of time from the inspiral volume data and subfile supplied. We
35 : * then construct a test ringdown domain that has all the corrected functions of
36 : * time from ComputeRingdownShapeAndTranslationFoT.py and an initial guess for
37 : * the inner radius. More details are outlined below.
38 : * \param path_to_volume_data The full path to the volume data containing the
39 : * domain and functions of time
40 : * \param volume_subfile_name Subfile containing volume data output from the
41 : * inspiral
42 : * \param path_to_horizons_h5 Path to h5 file containing horizon data for AhA/B
43 : * \param surface_subfile_name Subfile containing horizon data for AhA/B
44 : * \param path_to_AhC_distorted_h5 Path to h5 file containing ringdown shape
45 : * coefficients computed using ComputeRingdownShapeAndTranslationFoT.py
46 : * \param AhC_distorted_subfile_names Subfiles in the h5 file containing
47 : * shape coefficients
48 : * \param match_time The time to match the functions of time
49 : * \param settling_timescale Timescale at which the functions of time settle to
50 : * constant values
51 : * \param excision_A_radius The radius of excision A from the inspiral grid
52 : * frame
53 : * \param excision_B_radius The radius of excision B from the inspiral grid
54 : * frame
55 : * \param excision_A_center The center of excision A from the inspiral grid
56 : * frame
57 : * \param excision_B_center The center of excision B from the inspiral grid
58 : * frame
59 : * \param exp_func_and_2_derivs Expansion function of time from the inspiral
60 : * \param exp_outer_bdry_func_and_2_derivs Outer boundary expansion function of
61 : * time from the inspiral
62 : * \param rot_func_and_2_derivs Rotation function of time from the inspiral
63 : * \param trans_func_and_2_derivs The corrected translation function of time
64 : * computed by ComputeRingdownShapeAndTranslationFoT.py
65 : * \param match_time_tol The difference allowed between the match time requested
66 : * and the time found in h5 files
67 : *
68 : * Using the corrected functions of time and our initial guess for the ringdown
69 : * inner radius (the excision radius), excisions A/B are transformed from the
70 : * inertial frame to the ringdown grid frame. The inner radius is iterated upon
71 : * using 2 main loops, the outer loop which changes the L_max of the excisions
72 : * A/B being transformed from the inspiral and the inner loop that changes the
73 : * excision radius used in the ringdown. The general flow for these loops is as
74 : * follows:
75 : *
76 : * Let $ahc\_average\_radius$ be the average radius of the common horizon in the
77 : * inertial frame and since have strahlkorper data from the inertial frame AhC
78 : * we set $ahc\_average\_radius$ so that lambda00=0 at the match time.
79 : *
80 : * Let $ringdown\_excision\_radius$ be the radius of (spherical) excision
81 : * boundary in ringdown grid frame.
82 : *
83 : * Let $ringdown\_excision\_factor$ be the factor we multiply the
84 : * $ahc\_average\_radius$ by to get the $ringdown\_excision\_radius$.
85 : *
86 : * The goal is to find a good $ringdown\_excision\_factor$
87 : *
88 : * 1) Choose an initial guess for the $ringdown\_excision\_factor$. We choose
89 : * this to be 0.94 by default.
90 : *
91 : * 2) Choose an initial guess for current_l_max, the angular resolution of
92 : * spherical Strahlkorpers that match excision A and B (not horizons) in the
93 : * inspiral grid frame. We choose current_l_max=20 intially.
94 : *
95 : * 3) Construct Strahlkorpers in the Inspiral grid frame that correspond to
96 : * excisions A/B, the excision regions (not the horizons) of the two individual
97 : * holes. These are spherical in the inspiral grid frame, and have
98 : * L=current_l_max.
99 : *
100 : * 4) Map the Strahlkorper excisions A/B to the inertial frame. Now they are not
101 : * spherical.
102 : *
103 : * 4a) Using the current $ringdown\_excision\_factor$, construct a test domain
104 : * to map excisions A/B from the inertial frame to the ringdown grid frame. This
105 : * domain's functions of time should contain the scaling and rotation functions
106 : * of time from the inspiral that settle to const and the shape and corrected
107 : * translation function of time output by
108 : * ComputeRingdownShapeAndTranslationFoT.py
109 : *
110 : * 4b) Map the Strahlkorper excisions A/B to the Ringdown grid frame. They are
111 : * still not spherical.
112 : *
113 : * 4c) Loop through all the points on Ringdown grid excisions A/B, and find the
114 : * point that is the maximum distance from the origin. Call that maximum
115 : * distance $min\_excision\_radius$.
116 : *
117 : * 4d) A Ringdown grid sphere of radius $min\_excision\_radius$ centered at the
118 : * origin will (barely) enclose both excisions A/B, so choose
119 : * $minimum\_ringdown\_excision\_factor = \frac{min\_excision\_radius}
120 : * {ahc\_average\_radius}$ as the minimum possible $ringdown\_excision\_factor$.
121 : * And then choose the new value of $ringdown\_excision\_factor$ to be
122 : * \f{equation}{
123 : * ringdown\_excision\_factor=1-0.25*(1-minimum\_ringdown\_excision\_factor)
124 : * \f}
125 : * Which puts the excision radius 3/4 of the way between the
126 : * $ahc\_average\_radius$ and the $min\_excision\_radius$
127 : *
128 : * 4e) If this is the first inner iteration, or if
129 : * $|ringdown\_excision\_factor-previous\_ringdown\_excision\_factor|>eps$, then
130 : * set $previous\_ringdown\_excision\_factor=ringdown\_excision\_factor$ and
131 : * goto 3a, where 3a is repeated using the new $ringdown\_excision\_factor$. We
132 : * choose $eps = \frac{10^{-3}}{q}$ where q is an approximation of the mass
133 : * ratio. The reason this is iterative is because the new
134 : * $ringdown\_excision\_factor$ in 3d depends on the ringdown_excision_factor
135 : * used when constructing the test domain.
136 : *
137 : * 5) If we get here, then inner iteration has converged. But that iteration
138 : * depends on the $current\_l\_max$ used to construct excisions A/B in step 2.
139 : * If this is the first outer iteration, or if
140 : * $|ringdown\_excision\_factor-previous\_ringdown\_excision\_factor|>eps$, then
141 : * set $previous\_ringdown\_excision\_factor=ringdown\_excision\_factor$, and
142 : * increment $current\_l\_max$ by some increment (which we choose to be 6), and
143 : * go back to 2.
144 : *
145 : * 6) If we get here, the outer iteration is converged and now we have a final
146 : * $ringdown\_excision\_factor$.
147 : *
148 : * \note This implementation does not do everything SpEC does yet, it is
149 : * currently missing rescaling the shape coefficients held in
150 : * 'path_to_AhC_distorted_h5' by $excision\_radius / average\_ahc\_radius$ every
151 : * time it constructs a test ringdown domain. This step helps the shape of the
152 : * excision match the shape of the apparent horizon.
153 : */
154 1 : double minimum_ahc_excision_radius(
155 : const std::string& path_to_volume_data,
156 : const std::string& volume_subfile_name,
157 : const std::string& path_to_horizons_h5,
158 : const std::string& surface_subfile_name,
159 : const std::string& path_to_AhC_distorted_h5,
160 : const std::vector<std::string>& AhC_distorted_subfile_names,
161 : double match_time, double settling_timescale, double excision_A_radius,
162 : double excision_B_radius, std::array<double, 3> excision_A_center,
163 : std::array<double, 3> excision_B_center,
164 : const std::optional<std::array<double, 3>>& exp_func_and_2_derivs =
165 : std::nullopt,
166 : const std::optional<std::array<double, 3>>&
167 : exp_outer_bdry_func_and_2_derivs = std::nullopt,
168 : const std::optional<std::vector<std::array<double, 4>>>&
169 : rot_func_and_2_derivs = std::nullopt,
170 : const std::optional<std::array<std::array<double, 3>, 3>>&
171 : trans_func_and_2_derivs = std::nullopt,
172 : double match_time_tol = 1e-12);
173 : } // namespace evolution::Ringdown
|