25#include <lal/DetResponse.h>
26#include <lal/LALStdlib.h>
27#include <lal/LALConstants.h>
28#include <lal/AVFactories.h>
29#include <lal/SeqFactories.h>
30#include <lal/LIGOMetadataTables.h>
31#include <lal/LIGOMetadataInspiralUtils.h>
32#include <lal/LIGOMetadataRingdownUtils.h>
34#include <lal/SimulateCoherentGW.h>
35#include <lal/RingUtils.h>
36#include <lal/TimeDelay.h>
37#include <lal/TimeSeries.h>
38#include <lal/GenerateInspRing.h>
84 REAL4 polarization = 0;
96 REAL4 orbAngMom, totalAngMom;
109 if ( !waveform || !(waveform->
a->
data) || !(waveform->
f->
data) ||
112 XLALPrintError(
"Invalid waveform passed as input to %s\n", __func__);
119 "Length of waveform input to %s must be at least 2 points\n", __func__);
125 XLALPrintError(
"No sim inspiral table passed as input to %s\n", __func__);
135 ampPlus = waveform->
a->
data->
data[2*inputLength - 2];
136 ampPlusDot = ampPlus - waveform->
a->
data->
data[2*inputLength - 4];
138 ampCross = waveform->
a->
data->
data[2*inputLength - 1];
139 ampCrossDot = ampCross - waveform->
a->
data->
data[2*inputLength - 3];
141 freq0 = waveform->
f->
data->
data[inputLength - 1];
142 freqDot0 = freq0 - waveform->
f->
data->
data[inputLength - 2];
145 phase = waveform->
phi->
data->
data[inputLength - 1];
148 if ( waveform->
shift )
151 polDot = polarization - waveform->
shift->
data->
data[inputLength - 2];
155 "Final inspiral frequency = %.2f Hz, fdot = %.2e Hz/s\n"
156 "\n", freq0, freqDot0);
167 orbAngMom = 4 * inspiralInj->
eta * 0.7;
168 mTot = inspiralInj->
mass1 + inspiralInj->
mass2;
181 totalAngMom = pow(Jx * Jx + Jy * Jy + Jz * Jz, 0.5);
183 XLALPrintInfo(
"Approximate orbital ang mom = %.2f\n", orbAngMom);
184 XLALPrintInfo(
"Approximate total angular momentum of inspiral:\n"
185 "Jx = %.2f, Jy = %.2f, Jz = %.2f\n", Jx, Jy, Jz);
186 XLALPrintInfo(
"Estimated Final Spin = %.2f\n", totalAngMom );
190 mTot *= (1 - 0.01 * (1.0 + 6.0 * totalAngMom * totalAngMom ) );
191 ringInj->
mass = mTot;
195 ringInj->
spin = totalAngMom < 0.99 ? totalAngMom : 0.95;
198 LAL_PI * ( 1.0 - 0.63 * pow( ( 1.0 - ringInj->
spin ), 0.3 ) ) /
200 ringInj->
quality = 2.0 * pow( ( 1.0 - ringInj->
spin ), -0.45 );
203 "Estimated Ringdown Frequency = %.2f Hz, and Quality = %.2f\n"
211 "Ringdown longitude = %.2f, latitude = %.2f, distance = %.2f\n",
243 tToRing = 3 * freq0 / ( 8 * freqDot0 ) *
244 (1 - pow( freq0 / (0.9 * ringInj->
frequency), 8.0/3.0) );
245 mergerLength = ceil( tToRing /
dt ) - 1;
246 phi0 = phase +
LAL_TWOPI * 3 * freq0 * freq0 / (5 * freqDot0);
248 mergerPhase = phi0 - phase
249 - (
LAL_TWOPI) * (3.0 * freq0 * freq0 ) / ( 5.0 * freqDot0 ) *
250 pow( 1 - ( 8.0 * freqDot0 * tToRing) / ( 3.0 * freq0 ) , 5.0/8.0 );
254 XLALPrintInfo(
"Time to reach 0.9 of ringdown frequency = %.4f seconds,\n"
255 "%d data points, %.2f radians in GW phase\n"
256 "We then add the same length to asymptote to ringdown values\n",
257 tToRing, mergerLength, mergerPhase);
262 "The merger had a length of %.2f radians in GW phase (only allow 400 pi)\n"
263 "Returning null from %s\n",
264 mergerPhase, __func__);
275 dampFac = exp( - phaseFac / (2 * ringInj->
quality));
277 ringLength = ceil((24 * ringInj->
quality)/( phaseFac));
278 tRing = ringLength *
dt;
280 XLALPrintInfo(
"Time to damp the ringdown by exp(12) = %.4f seconds,\n"
281 "%d data points, %.2f radians in GW phase\n"
282 "\n", tRing, ringLength, ringLength * phaseFac);
287 outputLength = inputLength + 2 * mergerLength - 1 + ringLength;
300 2*outputLength*
sizeof(
REAL4) );
307 memset(waveform->
a->
data->
data + 2 * inputLength, 0,
308 2 * (outputLength - inputLength) *
sizeof(
REAL4) );
326 if ( waveform->
shift )
339 a = &(waveform->
a->
data->
data[2*inputLength]);
341 f = &(waveform->
f->
data->
data[inputLength]);
343 if ( waveform->
shift )
357 for (
n = 1;
n < mergerLength + 1;
n++ )
359 REAL4 factor = 1 - (8.0 * freqDot0 *
n *
dt) / (3.0 * freq0 );
360 freq = *(f++) = freq0 * pow( factor , -3.0/8.0 );
361 phase = *(phi++) = phi0 -
362 LAL_TWOPI * 3.0 * freq0 * freq0 / (5.0 * freqDot0) *
363 pow( factor , 5.0/8.0);
366 polarization = *(shift++) = polarization + polDot;
371 ringInj->
phase = phase;
378 freqDot = (freq - *(f - 2)) /
dt;
380 lambda = freqDot / A;
383 "Starting to asymptote to ringdown\n"
384 "Final 'merger' frequency = %.2f Hz, fdot = %.2e Hz/s\n",
387 "Frequency evolution fitted to freq = f_ring - A exp(-lambda t)\n"
388 "A = %.2f, lambda = %.2e\n"
392 for (
n = 1;
n < mergerLength + ringLength;
n++ )
395 freq = *(f++) = ringInj->
frequency - A * exp( -
n *
dt * lambda );
396 if ( (freq == ringInj->
frequency) && (condt == 0))
403 polDot *= exp( - lambda *
dt);
404 polarization = *(shift++) = polarization + polDot;
412 tRing2 += ( mergerLength + endMerger + 1.0) *
dt;
450 N = 2 * mergerLength;
452 a2Plus = ((dampFac - 1) * ( ampPlus +
N * ampPlusDot ) - ampPlusDot) /
453 ( 2*
N -
N*
N*(dampFac - 1) );
454 a2Cross = ((dampFac - 1) * ( ampCross +
N * ampCrossDot ) - ampCrossDot) /
455 ( 2*
N -
N*
N*(dampFac - 1) );
457 XLALPrintInfo(
"Fitting amplitude evolution to a quadratic\n"
458 "A = a_0 + a_1 * t + a_2 * t^2\n"
459 "For plus polarization, a_0 = %.2e, a_1 = %.2e, a_2 = %.2e\n"
460 "For cross polarization, a_0 = %.2e, a_1 = %.2e, a_2 = %.2e\n"
461 "\n", ampPlus, ampPlusDot /
dt, a2Plus / (
dt *
dt),
462 ampCross, ampCrossDot /
dt, a2Cross / (
dt *
dt) );
465 for (
n = 1;
n <
N;
n++ )
467 *(
a++) = ampPlus + ampPlusDot *
n + a2Plus *
n *
n;
468 *(
a++) = ampCross + ampCrossDot *
n + a2Cross *
n *
n;
475 for (
n = 0;
n < ringLength;
n++ )
477 ampPlus = *(
a++) = ampPlus * dampFac;
478 ampCross = *(
a++) = ampCross * dampFac;
482 n = 2.0*(inputLength + mergerLength + endMerger );
484 n = 2.0*(inputLength + mergerLength + endMerger ) + 1.0;
512 amp = ampPlus / ( 1.0 + cosiota * cosiota );
517 strstr(inspiralInj->
waveform,
"KludgeRingOnly") )
519 for (
n = 0;
n < 2.0*(inputLength + mergerLength + endMerger );
n++ )
535 double splus, scross, fplus, fcross;
536 double tDelay, tStart;
542 XLALPrintInfo(
"Calculating (approximate) parameters for the ringdown\n" );
545 strcpy( ringInj->
waveform,
"Ringdown" );
552 ( 1.0 + 4.0 * pow ( ringInj->
quality, 2 ) ) , 0.5);
576 "LHO: %d.%d GPS seconds\n"
577 "LLO: %d.%d GPS seconds\n",
583 splus = -( 1.0 + cosiota * cosiota );
584 scross = -2.0 * cosiota;
589 ringInj->
eff_dist_h /= sqrt( splus*splus*fplus*fplus +
590 scross*scross*fcross*fcross );
593 splus*splus*fplus*fplus +
594 2*pow(ringInj->
quality,2) * splus*scross*fplus*fcross +
595 2*pow(ringInj->
quality,3) * scross*scross*fcross*fcross )
597 ( 1.0 + 4.0 * pow ( ringInj->
quality, 2 ) ) , 0.5 );
598 XLALPrintInfo(
"LHO response: F+ = %f, Fx = %f\n", fplus, fcross);
605 ringInj->
eff_dist_l /= sqrt( splus*splus*fplus*fplus +
606 scross*scross*fcross*fcross );
609 splus*splus*fplus*fplus +
610 2*pow(ringInj->
quality,2) * splus*scross*fplus*fcross +
611 2*pow(ringInj->
quality,3) * scross*scross*fcross*fcross )
613 ( 1.0 + 4.0 * pow ( ringInj->
quality, 2 ) ) , 0.5 );
615 XLALPrintInfo(
"LLO response: F+ = %f, Fx = %f\n", fplus, fcross);
static SimRingdownTable * XLALDeriveRingdownParameters(SimRingdownTable *ringInj)
const LALDetector lalCachedDetectors[LAL_NUM_DETECTORS]
void XLALComputeDetAMResponse(double *fplus, double *fcross, const REAL4 D[3][3], const double ra, const double dec, const double psi, const double gmst)
CoherentGW * XLALGenerateInspRing(CoherentGW *waveform, SimInspiralTable *inspiralInj, SimRingdownTable *ringInj, int injectSignalType)
Takes an inspiral waveform, and a simInspiralTable and generates a ringdown at an appropriate frequen...
void * XLALRealloc(void *p, size_t n)
REAL4 XLALBlackHoleRingEpsilon(REAL4 f, REAL4 Q, REAL4 r, REAL4 amplitude)
REAL8 XLALTimeDelayFromEarthCenter(const double detector_earthfixed_xyz_metres[3], double source_right_ascension_radians, double source_declination_radians, const LIGOTimeGPS *gpstime)
REAL8TimeSeries * XLALResizeREAL8TimeSeries(REAL8TimeSeries *series, int first, size_t length)
REAL4TimeSeries * XLALResizeREAL4TimeSeries(REAL4TimeSeries *series, int first, size_t length)
#define XLAL_ERROR_NULL(...)
int int int XLALPrintInfo(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
REAL8 XLALGreenwichSiderealTime(const LIGOTimeGPS *gpstime, REAL8 equation_of_equinoxes)
LIGOTimeGPS * XLALGPSSetREAL8(LIGOTimeGPS *epoch, REAL8 t)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
REAL4TimeVectorSeries * a
REAL4VectorSequence * data
LIGOTimeGPS geocent_end_time
CHAR waveform[LIGOMETA_WAVEFORM_MAX]
CHAR waveform[LIGOMETA_WAVEFORM_MAX]
LIGOTimeGPS geocent_start_time
CHAR coordinates[LIGOMETA_COORDINATES_MAX]