00001 /* 00002 * Copyright (C) 2007 B.S. Sathyaprakash, Thomas Cokelaer 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with with program; see the file COPYING. If not, write to the 00016 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 00017 * MA 02111-1307 USA 00018 */ 00019 00020 /**** <lalVerbatim file="LALInspiralStationaryPhaseApprox1CV"> 00021 * Author: B.S. Sathyaprakash 00022 **** </lalVerbatim> */ 00023 00024 /**** <lalLaTeX> 00025 * 00026 * %% A one-line description of the function(s) defined in this module. 00027 * \subsection{Module \texttt{LALInspiralStationaryPhaseApprox1.c}} 00028 * This module computes the stationary phase approximation to the 00029 * Fourier transform of a chirp waveform by integrating Eq.~\ref{eq:InspiralFourierPhase}. 00030 * 00031 * \subsubsection*{Prototypes} 00032 * \input{LALInspiralStationaryPhaseApprox1CP} 00033 * \idx{LALInspiralStationaryPhaseApprox1()} 00034 * \begin{itemize} 00035 * \item {\tt signal:} Output containing the inspiral waveform. 00036 * \item {\tt params:} Input containing binary chirp parameters. 00037 * \end{itemize} 00038 * 00039 * \subsubsection*{Description} 00040 * 00041 * %% A description of the data analysis task performed by this function; 00042 * %% this is the main place to document the module. 00043 * This module generates the Fourier domain waveform that is analogous of 00044 * the time-domain approximant {\tt TaylorT1.} Instead of re-expanding the 00045 * the energy and flux functions they are kept in tact and the integral 00046 * in Eq.~(\ref{eq:InspiralFourierPhase}) is solved numerically. 00047 * The code returns the Fourier transform packed in the same way as fftw 00048 * would for the Fourier transform of a real vector. For a signal vector 00049 * of length {\tt n=signal->length} ({\tt n} even): 00050 * \begin{itemize} 00051 * \item {\tt signal->data[0]} is the {\it real} 0th frequency component of the Fourier transform. 00052 * \item {\tt signal->data[n/2]} is the {\it real} Nyquist frequency component of the Fourier transform. 00053 * \item {\tt signal->data[k]} and {\tt signal->data[n-k],} for {\tt k=1,\ldots, n/2-1,} are 00054 * the real and imaginary parts of the Fourier transform at a frequency $k\Delta f=k/T,$ $T$ being 00055 * the duration of the signal and $\Delta f=1/T$ is the frequency resolution. 00056 * \end{itemize} 00057 * 00058 * \subsubsection*{Algorithm} 00059 * 00060 * %% A description of the method used to perform the calculation. 00061 * The lal code {\tt LALDRomberIntegrate} is used to solve the 00062 * integral in Eq.~(\ref{eq:InspiralFourierPhase}). 00063 * The reference points are chosen so that on inverse Fourier transforming 00064 * the time-domain waveform will 00065 * \begin{itemize} 00066 * \item be padded with zeroes in the first {\tt params->nStartPad} bins, 00067 * \item begin with a phase shift of {\tt params->nStartPhase} radians, 00068 * \item have an amplitude of ${\tt n} v^2.$ 00069 * \end{itemize} 00070 * 00071 * \subsubsection*{Uses} 00072 * 00073 * %% List of any external functions called by this function. 00074 * \begin{verbatim} 00075 LALInspiralSetup 00076 LALInspiralChooseModel 00077 LALDRombergIntegrate 00078 * \end{verbatim} 00079 * \subsubsection*{Notes} 00080 * 00081 * %% Any relevant notes. 00082 * If it is required to compare the output of this module with a time domain 00083 * signal one should use an inverse Fourier transform routine that packs data 00084 * in the same way as fftw. Moreover, one should divide the resulting inverse 00085 * Fourier transform by a factor ${\tt n}/2$ to be consistent with the 00086 * amplitude used in time-domain signal models. 00087 * 00088 * 00089 * 00090 * \vfill{\footnotesize\input{LALInspiralStationaryPhaseApprox1CV}} 00091 * 00092 **** </lalLaTeX> */ 00093 00094 #include <lal/LALInspiral.h> 00095 #include <lal/Integrate.h> 00096 00097 /* a local function to compute the phase of the Fourier transform */ 00098 void 00099 LALPsiOfT ( 00100 LALStatus *stauts, 00101 REAL8 *psioft, 00102 REAL8 v, 00103 void *param 00104 ); 00105 00106 NRCSID (LALINSPIRALSTATIONARYPHASEAPPROX1C, "$Id: LALInspiralStationaryPhaseApprox1.c,v 1.6 2007/06/08 14:41:49 bema Exp $"); 00107 00108 /* This is the main function to compute the stationary phase approximation */ 00109 00110 /* <lalVerbatim file="LALInspiralStationaryPhaseApprox1CP"> */ 00111 void 00112 LALInspiralStationaryPhaseApprox1 ( 00113 LALStatus *status, 00114 REAL4Vector *signal, 00115 InspiralTemplate *params 00116 ) 00117 { /* </lalVerbatim> */ 00118 REAL8 t, pimmc, f0, fn, f, v, df, shft, phi, amp0, amp, psif, psi, sign; 00119 INT4 n, i, nby2; 00120 void *funcParams; 00121 DIntegrateIn intinp; 00122 TofVIntegrandIn psiIn; 00123 TofVIn tofvin; 00124 expnCoeffs ak; 00125 expnFunc func; 00126 00127 INITSTATUS (status, "LALInspiralStationaryPhaseApprox1", LALINSPIRALSTATIONARYPHASEAPPROX1C); 00128 ATTATCHSTATUSPTR(status); 00129 ASSERT (signal, status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL); 00130 ASSERT (signal->data, status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL); 00131 ASSERT (params, status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL); 00132 00133 /* Set up the coefficients in post-Newtonian expansion, vlso, etc. */ 00134 LALInspiralSetup (status->statusPtr, &ak, params); 00135 CHECKSTATUSPTR(status); 00136 /* Set up the functions required for the chosen signal approximation sheme */ 00137 LALInspiralChooseModel(status->statusPtr, &func, &ak, params); 00138 CHECKSTATUSPTR(status); 00139 00140 /* Cast the struct required for the phase function */ 00141 psiIn.dEnergy = func.dEnergy; 00142 psiIn.flux = func.flux; 00143 psiIn.coeffs = &ak; 00144 00145 /* Cast the struct required for computing initial conditions */ 00146 n = signal->length; 00147 nby2 = n/2; 00148 df = params->tSampling/signal->length; 00149 pimmc = LAL_PI * ak.totalmass; 00150 t = 0.0; 00151 tofvin.t = t; 00152 tofvin.v0 = ak.v0; 00153 tofvin.t0 = ak.t0; 00154 tofvin.vlso = ak.vlsoT2; 00155 tofvin.totalmass = ak.totalmass; 00156 tofvin.dEnergy = func.dEnergy; 00157 tofvin.flux = func.flux; 00158 tofvin.coeffs = &ak; 00159 00160 /* Compute the initial velocity frequency */ 00161 LALInspiralVelocity(status->statusPtr, &v, &tofvin); 00162 f0 = pow(v,3.L)/pimmc; 00163 fn = (params->fCutoff < ak.fn) ? params->fCutoff : ak.fn; 00164 00165 /* If we want to pad with zeroes in the beginning then the instant of 00166 * coalescence will be the chirp time + the duration for which padding 00167 * is needed. Thus, in the equation below nStartPad occurs with a +ve sign. 00168 */ 00169 shft = LAL_PI*2.L * (ak.tn + params->nStartPad/params->tSampling + params->startTime); 00170 phi = params->startPhase + LAL_PI/4.L; 00171 amp0 = params->signalAmplitude * ak.totalmass * pow(LAL_PI/12.L, 0.5L) * df; 00172 00173 signal->data[0] = 0.; 00174 signal->data[nby2] = 0.; 00175 /* 00176 Compute the standard stationary phase approximation. 00177 */ 00178 funcParams = (void *) &psiIn; 00179 intinp.function = LALPsiOfT; 00180 intinp.type = ClosedInterval; 00181 for (i=1; i<nby2; i++) 00182 { 00183 f = i * df; 00184 if (f<f0 || f>fn) 00185 { 00186 /* 00187 All frequency components below f0 and above fn are set to zero 00188 */ 00189 signal->data[i] = 0.; 00190 signal->data[n-i] = 0.; 00191 } 00192 else 00193 { 00194 ak.vf = v = pow(pimmc * f, oneby3); 00195 if (v==ak.v0) 00196 { 00197 psif = 0.; 00198 00199 } 00200 else 00201 { 00202 if (ak.v0 > ak.vf) 00203 { 00204 intinp.xmin = ak.vf; 00205 intinp.xmax = ak.v0; 00206 sign = -1.0; 00207 } 00208 else 00209 { 00210 intinp.xmin = ak.v0; 00211 intinp.xmax = ak.vf; 00212 sign = 1.0; 00213 } 00214 LALDRombergIntegrate (status->statusPtr, &psif, &intinp, funcParams); 00215 CHECKSTATUSPTR(status); 00216 psif *= sign; 00217 } 00218 psi = shft * f + phi + psif; 00219 /* 00220 dEnergybyFlux computes 1/(dv/dt) while what we need is 1/(dF/dt): 00221 dF/dt=(dF/dv)(dv/dt)=-dEnergybyFlux/(dF/dv)=-dEnergybyFlux 3v^2/(LAL_PI m^2) 00222 */ 00223 amp = amp0 * pow(-func.dEnergy(v,&ak)/func.flux(v,&ak),0.5) * v; 00224 signal->data[i] = (REAL4) (amp * cos(psi)); 00225 signal->data[n-i] = -(REAL4) (amp * sin(psi)); 00226 } 00227 } 00228 params->fFinal = fn; 00229 DETATCHSTATUSPTR(status); 00230 RETURN(status); 00231 } 00232 00233 void 00234 LALPsiOfT( 00235 LALStatus *status, 00236 REAL8 *psioft, 00237 REAL8 v, 00238 void *param 00239 ) 00240 { 00241 REAL8 vf, dE, F; 00242 TofVIntegrandIn *par; 00243 00244 status = NULL; 00245 par = (TofVIntegrandIn *) param; 00246 00247 /* The integrand below has an overall -ve sign as compared to 00248 * Eq. (3.5) of DIS3; this is because as oppsed to Eq. (3.5) of 00249 * DIS3 here we integrate from v0 to vf instead of from vf to v0. 00250 */ 00251 dE = par->dEnergy(v, par->coeffs); 00252 F = par->flux(v, par->coeffs); 00253 vf = par->coeffs->vf; 00254 *psioft = 2. * (v*v*v - vf*vf*vf) * dE/F; 00255 }
1.5.2