Skip to content

Commit 553aea4

Browse files
authored
Adding documentation for the PNBMS frame fixing method (#116)
1 parent 880be2a commit 553aea4

2 files changed

Lines changed: 280 additions & 112 deletions

File tree

docs/tutorial_abd.rst

Lines changed: 158 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,12 @@ that are easier to understand/analyze. Effectively, mapping to this frame amount
294294
in the center-of-mass frame, with no instananeous memory, and its angular velocity in the z-direction. For example,
295295
for a remnant black hole, this corresponds to making the coordinates match those of the usual Kerr metric and is
296296
therefore incredibly useful (and necessary) for fitting QNMs to NR waveforms.
297+
There is another choice of frame which we call the Post-Newtonian BMS frame (or
298+
PNBMS frame). In this frame, the waveform will agree with the Post-Newtonian
299+
description of the system at early times.
297300

298-
The function ``scri.asymptotic_bondi_data.map_to_superrest_frame`` maps to this exact frame.
301+
The function :meth:`scri.asymptotic_bondi_data.map_to_superrest_frame.map_to_superrest_frame` can map
302+
to one of these frames.
299303
In particular, it takes as input:
300304

301305
* ``t_0``, the time at which to map to the superrest frame;
@@ -333,7 +337,7 @@ It also can perform a number of other important post-processing steps, such as:
333337

334338
We recommend including all of these post-processing steps when processing SpECTRE CCE output.
335339

336-
To obtain the strain :math:`h` from the ``abd`` object, one can use the function ``scri.asymptotic_bondi_data.map_to_superrest_frame.MT_to_WM`` via ``h = MT_to_WM(2.0*abd.sigma.bar)``.
340+
To obtain the strain :math:`h` from the ``abd`` object, one can use the function :meth:`scri.asymptotic_bondi_data.map_to_superrest_frame.MT_to_WM` via ``h = MT_to_WM(2.0*abd.sigma.bar)``.
337341
This is because the strain :math:`h` is related to the shear :math:`\sigma` via :math:`h=2\overline{\sigma}`.
338342

339343
Example usage of this function could be:
@@ -357,10 +361,16 @@ Example usage of this function could be:
357361
For more on the :meth:`scri.WaveformModes` class, i.e., what :math:`h` is in the above code, see https://github.com/moble/scri/blob/main/docs/tutorial_waveformmodes.rst.
358362

359363
The CCE output is sometimes very densely sampled in time, which causes the BMS
360-
transformation to the superrest frame to take a long time (more than 10
364+
transformation to the superrest frame or PNBMS frame to take a long time (more than 10
361365
minutes). An effective way around this is to down sample the CCE data, compute
362-
the BMS transformation to the superrest frame with the down sampled data, and
363-
then apply to the full data. This can be done with the following two functions
366+
the BMS transformation to the appropriate frame with the down sampled data, and
367+
then apply to the full data.
368+
369+
--------------------------
370+
Fixing the superrest frame
371+
--------------------------
372+
The superrest frame of the CCE waveforms can be fixed using the following two
373+
functions.
364374

365375
.. code-block:: python
366376
@@ -387,6 +397,149 @@ then apply to the full data. This can be done with the following two functions
387397
frame_rotation=BMS.frame_rotation.components,
388398
boost_velocity=BMS.boost_velocity,)
389399
400+
------------------------------------------
401+
Fixing the PNBMS frame using PN CoM charge
402+
------------------------------------------
403+
404+
The PNBMS frame fixing of CCE waveforms requires ``target_PsiM_input`` (the PN
405+
Moreschi supermomentum), and ``target_strain_input`` (the PN strain). These
406+
post-Newtonian waveform modes can be generated using the `PostNewtonian.jl
407+
<https://github.com/moble/PostNewtonian.jl>`_ module. We can generate these
408+
waveform modes and provide them as input arguments to the
409+
``map_to_superrest_frame`` function for fixing the PNBMS frame. The generation
410+
of these waveform modes and fixing the frame can be performed using the
411+
following functions.
412+
413+
.. code-block:: python
414+
415+
from sxs.julia import PNWaveform
416+
import numpy as np
417+
import sxs
418+
import scri
419+
from scri.pn.boosted_comcharge import PN_charges, analytical_CoM_func
420+
421+
def generate_h_and_Psi_M_from_abd(abd, params, t0_pnbms, pnbms_padding):
422+
"""This function computes the target strain and target PsiM waveform
423+
required for PNBMS frame fixing.
424+
425+
Parameters
426+
----------
427+
abd : AsymptoticBondiData
428+
AsymptoticBondiData object from which the PN waveforms will be computed.
429+
params: tuple
430+
List of intrinsic parameters corresponding to the simulation. Its
431+
content should follow the form:
432+
params = M1, M2, chi1, chi2
433+
where M1, M2 are floats,
434+
chi1 : list of floats (n,3)
435+
chi2 : list of floats (n,3)
436+
t0_pnbms : float
437+
When to map to the PNBMS frame.
438+
pnbms_padding : float
439+
Amount by which to pad around t0 to speed up computations.
440+
This also determines the range over which certain BMS charges will be
441+
computed.
442+
443+
Returns
444+
-------
445+
h_pn_scri, Psi_M_scri : scri.WaveformModes object
446+
"""
447+
# First we create a window for frame-fixing using t0 and padding time.
448+
# The window is padded by an additional 200M on both sides of t0.
449+
t_left = t0_pnbms - (pnbms_padding + 200)
450+
t_right = t0_pnbms + (pnbms_padding + 200)
451+
452+
left_idx = np.abs(abd.t - t_left).argmin()
453+
right_idx = np.abs(abd.t - t_right).argmin()
454+
455+
h = abd.h[left_idx : right_idx]
456+
t = h.t - h.t[0]
457+
458+
N = h.copy()
459+
N.dataType = scri.hdot
460+
N.data = h.data_dot
461+
ω = np.linalg.norm(N.angular_velocity(), axis=1)[0]
462+
463+
# The convention for choosing the phase from h_{21} mode and the factor of
464+
# pi/2 is described in <https://arxiv.org/abs/2603.24661>. This choice
465+
# does not work for q=1.
466+
h_21 = h.data[:, h.index(2, 1)]
467+
θ = -1 * np.unwrap(np.angle(-h_21))[0] + np.pi/2
468+
469+
R_i = np.array([np.cos(θ / 2), 0, 0, np.sin(θ / 2)]).T
470+
471+
M1, M2, chi1, chi2 = params
472+
473+
h_PN = PNWaveform(M1, M2, chi1, chi2, ω, modes_function=sxs.julia.h_bang,
474+
R_i=R_i, saveat=t)
475+
Psi_M_PN = PNWaveform(M1, M2, chi1, chi2, ω,
476+
modes_function=sxs.julia.Ψ_M_bang, R_i=R_i, saveat=t)
477+
478+
# The PNWaveform function needs the kwarg times to start from t=0. Thus, we
479+
# translate the time array of PN waveform modes to match with the inspiral
480+
# window constructed from the abd object at the end.
481+
h_PN.t += t0_pnbms - (pnbms_padding + 200)
482+
Psi_M_PN.t += t0_pnbms - (pnbms_padding + 200)
483+
484+
# The sxs.WaveformModes objects should be converted to scri.WaveformModes
485+
# before passing to map_to_superrest_frame.
486+
h_pn_scri = scri.WaveformModes.from_sxs(h_PN)
487+
Psi_M_scri = scri.WaveformModes.from_sxs(Psi_M_PN)
488+
489+
h_pn_scri.data *= -1
490+
491+
return h_pn_scri, Psi_M_scri
492+
493+
def load_waveform_and_fix_to_pnbms(
494+
filename: str,
495+
params,
496+
dt: float = 1.0,
497+
t0_pnbms: float = 1800.0,
498+
pnbms_padding: float = 200.0,
499+
) -> scri.AsymptoticBondiData:
500+
abd = load_waveform(filename, dt)
501+
# params should take the same signature as it does in the previous
502+
# function.
503+
M1, M2, chi1, chi2 = params
504+
M = M1 + M2
505+
ν = M1 * M2 / M**2
506+
507+
# We use the parameters of the simulation, and the window information
508+
# (t0_pnbms and pnbms_padding) to generate PN strain and Moreschi
509+
# supermomentum modes data during that window.
510+
h_PN, Psi_M_PN = generate_h_and_Psi_M_from_abd(abd, params, t0_pnbms, pnbms_padding)
511+
512+
# Compute the BMS transformation to the PNBMS frame and the transformed
513+
# abd object.
514+
abd_prime, BMS, _ = abd.map_to_superrest_frame(
515+
t_0=t0_pnbms,
516+
padding_time=pnbms_padding,
517+
target_PsiM_input=Psi_M_PN,
518+
target_strain_input=h_PN,
519+
Gfun=analytical_CoM_func,
520+
Gparams0=np.zeros(8),
521+
Gargsfun=PN_charges(M, ν),
522+
)
523+
524+
return abd_prime
525+
526+
527+
This is the recent method for fixing the PNBMS frame described in Khairnar et
528+
al. `<https://arxiv.org/abs/2603.24661>`_. The function ``map_to_superrest_frame``
529+
takes 3 additional keyword arguments - ``Gfun``, ``Gparams0`` and ``Gargsfun``. ``Gfun``
530+
is the analtyical function used for fitting the CoM charge, ``Gparams0`` is the
531+
initial guess for the fitting parameters, and ``Gargsfun`` are additional
532+
arguments passed to Gfun. See the documentation of
533+
:meth:`scri.asymptotic_bondi_data.map_to_superrest_frame.com_transformation_to_map_to_superrest_frame`
534+
in :meth:`scri.asymptotic_bondi_data.map_to_superrest_frame` for additional
535+
details on the signature of ``Gfun`` and ``Gargsfun``.
536+
537+
Note that we have used :math:`h_{21}` mode to define the initial phase for the
538+
PN waveform. This choice won't work for symmetric mass ratio systems because
539+
of the degeneracy in the choice of phase angle by :math:`\pi`. Therefore, we
540+
will have to carefully choose the initial phase to break this degeneracy for
541+
such cases.
542+
390543
The parameter `dt` can be used to choose the time sampling for the
391544
waveform ABD object you get back, with default of `1M`. Reducing the time
392545
sampling for the waveform ABD is also useful if the CCE data was written too

0 commit comments

Comments
 (0)