REAL8 calculate_lalsim_snr(SimInspiralTable *inj, char *IFOname, REAL8FrequencySeries *psd, REAL8 start_freq) { /* Calculate and return the single IFO SNR * * Required options: * * inj: SimInspiralTable entry for which the SNR has to be calculated * IFOname: The canonical name (e.g. H1, L1, V1) name of the IFO for which the SNR must be calculated * PSD: PSD curve to be used for the overlap integrap * start_freq: lower cutoff of the overlap integral * * */ int ret=0; INT4 errnum=0; UINT4 j=0; /* Fill detector site info */ LALDetector* detector=NULL; detector=calloc(1,sizeof(LALDetector)); if(!strcmp(IFOname,"H1")) memcpy(detector,&lalCachedDetectors[LALDetectorIndexLHODIFF],sizeof(LALDetector)); if(!strcmp(IFOname,"H2")) memcpy(detector,&lalCachedDetectors[LALDetectorIndexLHODIFF],sizeof(LALDetector)); if(!strcmp(IFOname,"LLO")||!strcmp(IFOname,"L1")) memcpy(detector,&lalCachedDetectors[LALDetectorIndexLLODIFF],sizeof(LALDetector)); if(!strcmp(IFOname,"V1")||!strcmp(IFOname,"VIRGO")) memcpy(detector,&lalCachedDetectors[LALDetectorIndexVIRGODIFF],sizeof(LALDetector)); Approximant approx=TaylorF2; approx=XLALGetApproximantFromString(inj->waveform); LALSimulationDomain modelDomain; if(XLALSimInspiralImplementedFDApproximants(approx)) modelDomain = LAL_SIM_DOMAIN_FREQUENCY; else if(XLALSimInspiralImplementedTDApproximants(approx)) modelDomain = LAL_SIM_DOMAIN_TIME; else { fprintf(stderr,"ERROR. Unknown approximant number %i. Unable to choose time or frequency domain model.",approx); exit(1); } REAL8 m1,m2, s1x,s1y,s1z,s2x,s2y,s2z,phi0,f_min,f_max,iota,polarization, /* No tidal PN terms until injtable is able to get them */ lambda1=0.0,lambda2=0.0; LALSimInspiralWaveformFlags *waveFlags= XLALSimInspiralCreateWaveformFlags(); /* Spin and tidal interactions at the highest level (default) until injtable stores them. * When spinO and tideO are added to injtable we can un-comment those lines and should be ok * int spinO = inj->spinO; int tideO = inj->tideO; XLALSimInspiralSetSpinOrder(waveFlags, *(LALSimInspiralSpinOrder*) spinO); XLALSimInspiralSetTidalOrder(waveFlags, *(LALSimInspiralTidalOrder*) tideO); */ /* When nonGR terms stored in the table, we can add them here. (If they are only phase deformations, they won't change the SNR though) */ LALSimInspiralTestGRParam *nonGRparams=NULL; /* Linked list of non-GR parameters. Pass in NULL (or None in python) for standard GR waveforms */ LALPNOrder order; /* Phase order of the model */ INT4 amporder=0; order = XLALGetOrderFromString(inj->waveform); amporder = inj->amp_order; /* Read parameters */ m1=inj->mass1*LAL_MSUN_SI; m2=inj->mass2*LAL_MSUN_SI; s1x=inj->spin1x; s1y=inj->spin1y; s1z=inj->spin1z; s2x=inj->spin2x; s2y=inj->spin2y; s2z=inj->spin2z; iota=inj->inclination; f_min=start_freq; phi0=inj->coa_phase; polarization=inj->polarization; REAL8 latitude=inj->latitude; REAL8 longitude=inj->longitude; LIGOTimeGPS epoch; memcpy(&epoch,&(inj->geocent_end_time),sizeof(LIGOTimeGPS)); /* Hardcoded values of srate and segment length. If changed here they must also be changed in inspinj.c */ REAL8 srate=4096.0; const CHAR *WF=inj->waveform; /* Increase srate for EOB WFs */ if (strstr(WF,"EOB")) srate=8192.0; REAL8 segment=64.0; f_max=(srate/2.0-(1.0/segment)); size_t seglen=(size_t) segment*srate; REAL8 deltaF=1.0/segment; REAL8 deltaT=1.0/srate; /* Frequency domain h+ and hx. They are going to be filled either by a FD WF or by the FFT of a TD WF*/ COMPLEX16FrequencySeries *freqHplus; COMPLEX16FrequencySeries *freqHcross; freqHplus= XLALCreateCOMPLEX16FrequencySeries("fhplus", &epoch, 0.0, deltaF, &lalDimensionlessUnit, seglen/2+1 ); freqHcross=XLALCreateCOMPLEX16FrequencySeries("fhcross", &epoch, 0.0, deltaF, &lalDimensionlessUnit, seglen/2+1 ); /* If the approximant is on the FD call XLALSimInspiralChooseFDWaveform */ if (modelDomain == LAL_SIM_DOMAIN_FREQUENCY) { COMPLEX16FrequencySeries *hptilde=NULL; COMPLEX16FrequencySeries *hctilde=NULL; XLAL_TRY(ret=XLALSimInspiralChooseFDWaveform(&hptilde,&hctilde, phi0, deltaF, m1, m2, s1x, s1y, s1z, s2x, s2y, s2z, f_min, 0.0, 0.0, LAL_PC_SI * 1.0e6, iota, lambda1, lambda2, waveFlags, nonGRparams, amporder, order, approx),errnum ); if(!hptilde|| hptilde->data==NULL || hptilde->data->data==NULL ||!hctilde|| hctilde->data==NULL || hctilde->data->data==NULL) { XLALPrintError(" ERROR in XLALSimInspiralChooseFDWaveform(): error generating waveform. errnum=%d. Exiting...\n",errnum ); exit(1); } COMPLEX16 *dataPtr = hptilde->data->data; for (j=0; j<(UINT4) freqHplus->data->length; ++j) { if(j < hptilde->data->length) { freqHplus->data->data[j] = dataPtr[j]; } else { freqHplus->data->data[j]=0.0 + I*0.0; } } dataPtr = hctilde->data->data; for (j=0; j<(UINT4) freqHplus->data->length; ++j) { if(j < hctilde->data->length) { freqHcross->data->data[j] = dataPtr[j]; } else { freqHcross->data->data[j]=0.0+0.0*I; } } /* Clean */ if(hptilde) XLALDestroyCOMPLEX16FrequencySeries(hptilde); if(hctilde) XLALDestroyCOMPLEX16FrequencySeries(hctilde); } else { /* Otherwise use XLALSimInspiralChooseTDWaveform */ REAL8FFTPlan *timeToFreqFFTPlan = XLALCreateForwardREAL8FFTPlan((UINT4) seglen, 0 ); REAL8TimeSeries *hplus=NULL; REAL8TimeSeries *hcross=NULL; REAL8TimeSeries *timeHplus=NULL; REAL8TimeSeries *timeHcross=NULL; REAL8 padding =0.4;//seconds REAL8Window *window=XLALCreateTukeyREAL8Window(seglen,(REAL8)2.0*padding*srate/(REAL8)seglen); REAL4 WinNorm = sqrt(window->sumofsquares/window->data->length); timeHcross=XLALCreateREAL8TimeSeries("timeModelhCross", &epoch, 0.0, deltaT, &lalStrainUnit, seglen ); timeHplus=XLALCreateREAL8TimeSeries("timeModelhplus", &epoch, 0.0, deltaT, &lalStrainUnit, seglen ); for (j=0;j<(UINT4) timeHcross->data->length;++j) timeHcross->data->data[j]=0.0; for (j=0;j<(UINT4) timeHplus->data->length;++j) timeHplus->data->data[j]=0.0; XLAL_TRY(ret=XLALSimInspiralChooseTDWaveform(&hplus, &hcross, phi0, deltaT, m1, m2, s1x, s1y, s1z, s2x, s2y, s2z, f_min, 0., LAL_PC_SI*1.0e6, iota, lambda1, lambda2, waveFlags, nonGRparams, amporder, order, approx), errnum); if (ret == XLAL_FAILURE || hplus == NULL || hcross == NULL) { XLALPrintError(" ERROR in XLALSimInspiralChooseTDWaveform(): error generating waveform. errnum=%d. Exiting...\n",errnum ); exit(1); } XLALSimAddInjectionREAL8TimeSeries(timeHplus, hplus, NULL); XLALSimAddInjectionREAL8TimeSeries(timeHcross, hcross, NULL); for (j=0; j<(UINT4) timeHplus->data->length; ++j) timeHplus->data->data[j]*=window->data->data[j]; for (j=0; j<(UINT4) timeHcross->data->length; ++j) timeHcross->data->data[j]*=window->data->data[j]; for (j=0; j<(UINT4) freqHplus->data->length; ++j) { freqHplus->data->data[j]=0.0+I*0.0; freqHcross->data->data[j]=0.0+I*0.0; } /* FFT into freqHplus and freqHcross */ XLALREAL8TimeFreqFFT(freqHplus,timeHplus,timeToFreqFFTPlan); XLALREAL8TimeFreqFFT(freqHcross,timeHcross,timeToFreqFFTPlan); for (j=0; j<(UINT4) freqHplus->data->length; ++j) { freqHplus->data->data[j]/=WinNorm; freqHcross->data->data[j]/=WinNorm; } /* Clean... */ if ( hplus ) XLALDestroyREAL8TimeSeries(hplus); if ( hcross ) XLALDestroyREAL8TimeSeries(hcross); if ( timeHplus ) XLALDestroyREAL8TimeSeries(timeHplus); if ( timeHcross ) XLALDestroyREAL8TimeSeries(timeHcross); if (timeToFreqFFTPlan) LALFree(timeToFreqFFTPlan); if (window) XLALDestroyREAL8Window(window); } /* The WF has been generated and is in freqHplus/cross. Now project into the IFO frame */ double Fplus, Fcross; double FplusScaled, FcrossScaled; double HSquared; double GPSdouble=(REAL8) inj->geocent_end_time.gpsSeconds+ (REAL8) inj->geocent_end_time.gpsNanoSeconds*1.0e-9; double gmst; LIGOTimeGPS GPSlal; XLALGPSSetREAL8(&GPSlal, GPSdouble); gmst=XLALGreenwichMeanSiderealTime(&GPSlal); /* Fill Fplus and Fcross*/ XLALComputeDetAMResponse(&Fplus, &Fcross, (const REAL4 (*)[3])detector->response,longitude, latitude, polarization, gmst); /* And take the distance into account */ FplusScaled = Fplus / (inj->distance); FcrossScaled = Fcross / (inj->distance); REAL8 timedelay = XLALTimeDelayFromEarthCenter(detector->location,longitude, latitude, &GPSlal); REAL8 timeshift = timedelay; REAL8 twopit = LAL_TWOPI * timeshift; UINT4 lower = (UINT4)ceil(f_min / deltaF); UINT4 upper = (UINT4)floor(f_max / deltaF); REAL8 re = cos(twopit*deltaF*lower); REAL8 im = -sin(twopit*deltaF*lower); /* Incremental values, using cos(theta) - 1 = -2*sin(theta/2)^2 */ REAL8 dim = -sin(twopit*deltaF); REAL8 dre = -2.0*sin(0.5*twopit*deltaF)*sin(0.5*twopit*deltaF); REAL8 TwoDeltaToverN = 2.0 *deltaT / ((double) seglen); REAL8 plainTemplateReal, plainTemplateImag,templateReal,templateImag; REAL8 newRe, newIm,temp; REAL8 this_snr=0.0; for (j=lower; j<=(UINT4) upper; ++j) { /* derive template (involving location/orientation parameters) from given plus/cross waveforms: */ plainTemplateReal = FplusScaled * creal(freqHplus->data->data[j]) + FcrossScaled *creal(freqHcross->data->data[j]); plainTemplateImag = FplusScaled * cimag(freqHplus->data->data[j]) + FcrossScaled * cimag(freqHcross->data->data[j]); /* do time-shifting... */ /* (also un-do 1/deltaT scaling): */ templateReal = (plainTemplateReal*re - plainTemplateImag*im) / deltaT; templateImag = (plainTemplateReal*im + plainTemplateImag*re) / deltaT; HSquared = templateReal*templateReal + templateImag*templateImag ; temp = ((TwoDeltaToverN * HSquared) / psd->data->data[j]); this_snr += temp; /* Now update re and im for the next iteration. */ newRe = re + re*dre - im*dim; newIm = im + re*dim + im*dre; re = newRe; im = newIm; } /* Clean */ if (freqHcross) XLALDestroyCOMPLEX16FrequencySeries(freqHcross); if (freqHplus) XLALDestroyCOMPLEX16FrequencySeries(freqHplus); if (waveFlags) XLALSimInspiralDestroyWaveformFlags(waveFlags); if (nonGRparams) XLALSimInspiralDestroyTestGRParam(nonGRparams); if (detector) free(detector); return sqrt(this_snr*2.0); }
/* * main */ int main (int argc , char **argv) { FILE *f; int status; int start_time; COMPLEX16FrequencySeries *hptilde = NULL, *hctilde = NULL; REAL8TimeSeries *hplus = NULL; REAL8TimeSeries *hcross = NULL; GSParams *params; /* set us up to fail hard */ XLALSetErrorHandler(XLALAbortErrorHandler); /* parse commandline */ params = parse_args(argc, argv); /* generate waveform */ start_time = time(NULL); switch (params->domain) { case LAL_SIM_DOMAIN_FREQUENCY: XLALSimInspiralChooseFDWaveform(&hptilde, &hctilde, params->phiRef, params->deltaF, params->m1, params->m2, params->s1x, params->s1y, params->s1z, params->s2x, params->s2y, params->s2z, params->f_min, params->f_max, params->fRef, params->distance, params->inclination, params->lambda1, params->lambda2, params->waveFlags, params->nonGRparams, params->ampO, params->phaseO, params->approximant); break; case LAL_SIM_DOMAIN_TIME: XLALSimInspiralChooseTDWaveform(&hplus, &hcross, params->phiRef, params->deltaT, params->m1, params->m2, params->s1x, params->s1y, params->s1z, params->s2x, params->s2y, params->s2z, params->f_min, params->fRef, params->distance, params->inclination, params->lambda1, params->lambda2, params->waveFlags, params->nonGRparams, params->ampO, params->phaseO, params->approximant); break; default: XLALPrintError("Error: domain must be either TD or FD\n"); } if (params->verbose) XLALPrintInfo("Generation took %.0f seconds\n", difftime(time(NULL), start_time)); if (((params->domain == LAL_SIM_DOMAIN_FREQUENCY) && (!hptilde || !hctilde)) || ((params->domain == LAL_SIM_DOMAIN_TIME) && (!hplus || !hcross))) { XLALPrintError("Error: waveform generation failed\n"); goto fail; } /* dump file */ if ( strlen(params->outname) > 0 ) { f = fopen(params->outname, "w"); if (f==NULL) { printf("**ERROR** Impossible to write file %s\n",params->outname); exit(1); } else { if (params->domain == LAL_SIM_DOMAIN_FREQUENCY) if (params->ampPhase == 1) status = dump_FD2(f, hptilde, hctilde); else status = dump_FD(f, hptilde, hctilde); else if (params->ampPhase == 1) status = dump_TD2(f, hplus, hcross); else status = dump_TD(f, hplus, hcross); fclose(f); } if (status) goto fail; } /* clean up */ XLALSimInspiralDestroyWaveformFlags(params->waveFlags); XLALSimInspiralDestroyTestGRParam(params->nonGRparams); XLALFree(params); XLALDestroyCOMPLEX16FrequencySeries(hptilde); XLALDestroyCOMPLEX16FrequencySeries(hctilde); return 0; fail: XLALSimInspiralDestroyWaveformFlags(params->waveFlags); XLALSimInspiralDestroyTestGRParam(params->nonGRparams); XLALFree(params); XLALDestroyCOMPLEX16FrequencySeries(hptilde); XLALDestroyCOMPLEX16FrequencySeries(hctilde); return 1; }
int main(void){ FILE* h_ref = fopen("h_ref_PhenomB.txt", "w"); FILE* h_rot = fopen("h_rot_PhenomB.txt", "w"); int ret; unsigned int i; // Waveform parameters double m1 = 2.0*LAL_MSUN_SI, m2 = 5.0*LAL_MSUN_SI; double s1x = 0.0, s1y = 0.0, s1z = 0.0; double s2x = 0.0, s2y = 0.0, s2z = 0.0; double f_min = 40.0, f_ref = 0.0, dist = 1e6*LAL_PC_SI, inc = LAL_PI_4; double lambda1 = 0.0, lambda2 = 0.0; double phi = 0.0, dt = 1/16384.0; LALSimInspiralWaveformFlags *waveFlags = NULL; LALSimInspiralTestGRParam *nonGRparams = NULL; int amplitudeOrder = 0, phaseOrder = 7; Approximant approximant = IMRPhenomB; double view_th = 0.0, view_ph = 0.0; double Y_2_m2 = XLALSpinWeightedSphericalHarmonic( view_th + LAL_PI, view_ph, -2, 2, -2), Y_22 = XLALSpinWeightedSphericalHarmonic( view_th, view_ph, -2, 2, 2); REAL8TimeSeries *hp, *hx; hp = NULL; hx = NULL; ret = XLALSimInspiralChooseTDWaveform( &hp, &hx, phi, dt, m1, m2, s1x, s1y, s1z, s2x, s2y, s2z, f_min, f_ref, dist, inc, lambda1, lambda2, waveFlags, nonGRparams, amplitudeOrder, phaseOrder, approximant ); if( ret != XLAL_SUCCESS ) XLAL_ERROR( XLAL_EFUNC ); COMPLEX16TimeSeries *h_22, *h_2_2; h_22 = NULL; h_2_2 = NULL; // Initialize the h_lm REAL8 vectors h_2_2 = XLALCreateCOMPLEX16TimeSeries( "h_{2-2}", &(hp->epoch), hp->f0, hp->deltaT, &(hp->sampleUnits), hp->data->length ); // Define h_{2-2} for( i=0; i< hp->data->length; i++ ){ h_2_2->data->data[i] = (hp->data->data[i] + 1I * hx->data->data[i]) / Y_2_m2; } XLALDestroyREAL8TimeSeries( hp ); XLALDestroyREAL8TimeSeries( hx ); hp = NULL; hx = NULL; inc=0; // +z axis ret = XLALSimInspiralChooseTDWaveform( &hp, &hx, phi, dt, m1, m2, s1x, s1y, s1z, s2x, s2y, s2z, f_min, f_ref, dist, inc, lambda1, lambda2, waveFlags, NULL, // non-GR params amplitudeOrder, phaseOrder, approximant ); if( ret != XLAL_SUCCESS ) XLAL_ERROR( XLAL_EFUNC ); // Initialize the h_lm REAL8 vectors h_22 = XLALCreateCOMPLEX16TimeSeries( "h_{22}", &(hp->epoch), hp->f0, hp->deltaT, &(hp->sampleUnits), hp->data->length ); // Define h_{22} for( i=0; i< hp->data->length; i++ ){ h_22->data->data[i] = (hp->data->data[i] + 1I * hx->data->data[i]) / Y_22; } // Write out reference waveform REAL8 t0 = XLALGPSGetREAL8(&(hp->epoch)); for(i=0; i<hp->data->length; i++) fprintf( h_ref, "%g %g %g\n", t0 + i * hp->deltaT, hp->data->data[i], hx->data->data[i] ); XLALSimInspiralDestroyWaveformFlags( waveFlags ); SphHarmTimeSeries *ts = NULL; ts = XLALSphHarmTimeSeriesAddMode( ts, h_22, 2, 2 ); ts = XLALSphHarmTimeSeriesAddMode( ts, h_2_2, 2, -2 ); ret = XLALSimInspiralConstantPrecessionConeWaveform( &hp, &hx, ts, 10, LAL_PI/4, 0, 0, LAL_PI/4 ); if( ret != XLAL_SUCCESS ) XLAL_ERROR( XLAL_EFUNC ); XLALDestroyCOMPLEX16TimeSeries( h_22 ); XLALDestroyCOMPLEX16TimeSeries( h_2_2 ); XLALDestroySphHarmTimeSeries( ts ); // Write out rotated waveform for(i=0; i<hp->data->length; i++) fprintf( h_rot, "%g %g %g\n", t0 + i * hp->deltaT, hp->data->data[i], hx->data->data[i] ); // We're done. XLALDestroyREAL8TimeSeries( hp ); XLALDestroyREAL8TimeSeries( hx ); fclose(h_ref); fclose(h_rot); return 0; }