LALInspiralSpinningBHBinary.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Jolien Creighton, B.S. Sathyaprakash, Craig Robinson , 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="LALInspiralSpinningBHBinaryCV">
00021 Author: Sathyaprakash, B. S.
00022 $Id: LALInspiralSpinningBHBinary.c,v 1.12 2007/06/08 14:41:49 bema Exp $
00023 </lalVerbatim>  */
00024 
00025 /*  <lalLaTeX>
00026 
00027 \subsection{Module \texttt{LALInspiralSpinningBHBinary.c}}
00028 
00029 This module generates the inspiral waveform from a binary consisting of
00030 two spinning compact stars. 
00031 
00032 \subsubsection*{Prototypes}
00033 \vspace{0.1in}
00034 \input{LALInspiralSpinningBHBinaryCP}
00035 \index{\verb&LALInspiralSpinningBHBinary()&}
00036 \begin{itemize}
00037 \item {\tt signal:} Output containing the spin modulated inspiral waveform.
00038 \item {\tt in:} Input containing binary chirp parameters.
00039 \end{itemize}
00040 
00041 \subsubsection*{Description}
00042 Using the formalism described in Apostolatos 
00043 et al \cite{ACST94} and Blanchet et al. \cite{BDIWW} and formulas
00044 summarized in Sec.~\ref{sec:smirches} this module computes
00045 the spin-modulated chirps from a pair of compact stars in orbit around
00046 each other. 
00047  
00048 \subsubsection*{Algorithm}
00049 This code uses a fourth-order Runge-Kutta algorithm to solve the nine 
00050 first-order, coupled, ordinary differential equations in Eq.~\ref{eqn:precession1}
00051 Eq.~\ref{eqn:precession2} and Eq.~\ref{eqn:precession3}. The solution is then used
00052 in Eq.~\ref{eq:waveform} (and following equations) to get the waveform  emitted
00053 by a spinning black hole binary.
00054 
00055 \subsubsection*{Uses}
00056 
00057 \texttt{LALInspiralSetup}\\
00058 \texttt{LALInspiralChooseModel}\\
00059 \texttt{LALInspiralVelocity}\\
00060 \texttt{LALInspiralPhasing3}\\
00061 \texttt{LALRungeKutta4}.
00062  
00063 \subsubsection*{Notes}
00064 
00065 \vfill{\footnotesize\input{LALInspiralSpinningBHBinaryCV}}
00066 
00067 </lalLaTeX>  */
00068 
00069 /* 
00070    Interface routine needed to generate time-domain T- or a P-approximant
00071    waveforms by solving the ODEs using a 4th order Runge-Kutta; April 5, 00.
00072 */
00073 #include <lal/LALInspiral.h>
00074 #include <lal/LALStdlib.h>
00075 #include <lal/Units.h>
00076 #include <lal/SeqFactories.h>
00077 
00078 
00079 /* computes the polarisation angle psi */ 
00080 static void LALInspiralPolarisationAngle( REAL8 *psi, REAL8 psiOld, REAL8 *NCap, REAL8 *L);
00081 /* compute beam factors Fplus and Fcross */
00082 static void LALInspiralBeamFactors(REAL8 *Fplus, REAL8 *Fcross, REAL8 Fp0, REAL8 Fp1, REAL8 Fc0, REAL8 Fc1, REAL8 psi);
00083 /* compute polarisation phase phi */
00084 static void LALInspiralPolarisationPhase(REAL8 *phi, REAL8 phiOld, REAL8 NCapDotLByL, REAL8 Fplus, REAL8 Fcross); 
00085 /* computes modulated amplitude A */
00086 static void LALInspiralModulatedAmplitude(REAL8 *amp, REAL8 v, REAL8 amp0, REAL8 NCapDotLByL, REAL8 Fplus, REAL8 Fcross);
00087 /* computes the derivatives of vectors L, S1 and S2 */
00088 void LALACSTDerivatives (REAL8Vector *values, REAL8Vector *dvalues, void *funcParams);
00089 
00090 /* computes carrier phase Phi */
00091 /* func.phasing3(LALStatus *status, REAL8 *Phi, REAL8 Theta, REAL8 *ak); */
00092 
00093 /* computes precession correction to phase dThi */
00094 
00095 
00096 NRCSID (LALINSPIRALSPINNINGBHBINARYC, "$Id: LALInspiralSpinningBHBinary.c,v 1.12 2007/06/08 14:41:49 bema Exp $");
00097 
00098 /* Routine to generate inspiral waveforms from binaries consisting of spinning objects */
00099 /*  <lalVerbatim file="LALInspiralSpinningBHBinaryCP"> */
00100 void 
00101 LALInspiralSpinModulatedWave(
00102    LALStatus        *status, 
00103    REAL4Vector      *signal, 
00104    InspiralTemplate *in
00105    )
00106 { /* </lalVerbatim> */
00107 
00108 
00109         UINT4 nDEDim=9/*, Dim=3*/;
00110         UINT4 j, count;
00111         /* polarisation and antenna pattern */
00112         REAL8 psi, psiOld, Fplus, Fcross, Fp0, Fp1, Fc0, Fc1, magL, amp, amp0, phi, phiOld, /*Amplitude,*/ Phi/*, dPhi*/;
00113         REAL8 v, t, tMax, dt, f, fOld, fn, phase, phi0, MCube, Theta, etaBy5M, NCapDotL, NCapDotLByL;
00114         /* source direction angles */
00115         InspiralACSTParams acstPars;
00116         REAL8Vector dummy, values, dvalues, newvalues, yt, dym, dyt;
00117         void *funcParams;
00118         rk4In rk4in;
00119         rk4GSLIntegrator *integrator;
00120         expnFunc func;
00121         expnCoeffs ak;
00122 
00123    
00124         INITSTATUS(status, "LALInspiralSpinngBHBinary", LALINSPIRALSPINNINGBHBINARYC);
00125         ATTATCHSTATUSPTR(status);
00126         ASSERT(signal,  status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL);
00127         ASSERT(signal->data,  status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL);
00128         ASSERT(in,  status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL);
00129   
00130         LALInspiralSetup (status->statusPtr, &ak, in);
00131         CHECKSTATUSPTR(status);
00132         LALInspiralChooseModel(status->statusPtr, &func, &ak, in);
00133         CHECKSTATUSPTR(status);
00134 
00135         /* Allocate space for all the vectors in one go ... */
00136    
00137         dummy.length = nDEDim * 6;
00138         values.length = dvalues.length = newvalues.length = yt.length = dym.length = dyt.length = nDEDim;
00139    
00140         if (!(dummy.data = (REAL8 *) LALMalloc(sizeof(REAL8) * dummy.length))) 
00141         {
00142                 ABORT(status, LALINSPIRALH_EMEM, LALINSPIRALH_MSGEMEM);
00143         }
00144    
00145         /* and distribute as necessary */
00146         values.data = &dummy.data[0];             /* values of L, S1, S2 at current time */
00147         dvalues.data = &dummy.data[nDEDim];       /* values of dL/dt, dS1/dt, dS2/dt at current time */
00148         newvalues.data = &dummy.data[2*nDEDim];   /* new values of L, S1, S2 after time increment by dt*/
00149         yt.data = &dummy.data[3*nDEDim];          /* Vector space needed by LALRungeKutta4 */
00150         dym.data = &dummy.data[4*nDEDim];         /* Vector space needed by LALRungeKutta4 */
00151         dyt.data = &dummy.data[5*nDEDim];         /* Vector space needed by LALRungeKutta4 */
00152 
00153         v = pow(LAL_PI * in->totalMass * LAL_MTSUN_SI * in->fLower, 1.L/3.L);
00154         MCube = pow(LAL_MTSUN_SI * in->totalMass, 3.L);
00155         /* Fill in the structure needed by the routine that computes the derivatives */
00156         /* constant spins of the two bodies */
00157         acstPars.magS1 = in->spin1[0]*in->spin1[0] + in->spin1[1]*in->spin1[1] + in->spin1[2]*in->spin1[2];
00158         acstPars.magS2 = in->spin2[0]*in->spin2[0] + in->spin2[1]*in->spin2[1] + in->spin2[2]*in->spin2[2];
00159         /* Direction to the source in the solar system barycenter */
00160         acstPars.NCap[0] = sin(in->sourceTheta)*cos(in->sourcePhi);
00161         acstPars.NCap[1] = sin(in->sourceTheta)*sin(in->sourcePhi);
00162         acstPars.NCap[2] = cos(in->sourceTheta);
00163         /* total mass in seconds */
00164         acstPars.M = LAL_MTSUN_SI * in->totalMass;
00165         /* Combination of masses that appears in the evolution of L, S1 and S2 */
00166         acstPars.fourM1Plus = (4.L*in->mass1 + 3.L*in->mass2)/(2.*in->mass1*MCube);
00167         acstPars.fourM2Plus = (4.L*in->mass2 + 3.L*in->mass1)/(2.*in->mass2*MCube);
00168         acstPars.oneBy2Mcube = 0.5L/MCube;
00169         acstPars.threeBy2Mcube = 1.5L/MCube;
00170         acstPars.thirtytwoBy5etc = (32.L/5.L) * pow(in->eta,2.) * acstPars.M;
00171 
00172         /* Constant amplitude of GW */
00173         amp0 = 2.L*in->eta * acstPars.M/in->distance;
00174         /* Initial magnitude of the angular momentum, determined by the initial frequency/velocity */
00175         magL = in->eta * (acstPars.M * acstPars.M)/v;
00176         /* Initial angular momentum and spin vectors */
00177         /* Angular momentum */
00178         values.data[0] = magL * sin(in->orbitTheta0) * cos(in->orbitPhi0);
00179         values.data[1] = magL * sin(in->orbitTheta0) * sin(in->orbitPhi0);
00180         values.data[2] = magL * cos(in->orbitTheta0);
00181         /* Spin of primary */
00182         values.data[3] = in->spin1[0];
00183         values.data[4] = in->spin1[1];
00184         values.data[5] = in->spin1[2];
00185         /* Spin of secondarfy */
00186         values.data[6] = in->spin2[0];
00187         values.data[7] = in->spin2[1];
00188         values.data[8] = in->spin2[2];
00189         /* Structure needed by RungeKutta4 for the evolution of the differential equations */
00190         rk4in.function = LALACSTDerivatives;
00191         rk4in.y = &values;
00192         rk4in.h = 1.L/in->tSampling;
00193         rk4in.n = nDEDim;
00194         rk4in.yt = &yt;
00195         rk4in.dym = &dym;
00196         rk4in.dyt = &dyt;
00197 
00198         xlalErrno = 0;
00199         /* Initialize GSL integrator */
00200         if (!(integrator = XLALRungeKutta4Init(nDEDim, &rk4in)))
00201         {
00202           INT4 errNum = XLALClearErrno();
00203           LALFree(dummy.data);
00204 
00205           if (errNum = XLAL_ENOMEM)
00206             ABORT(status, LALINSPIRALH_EMEM, LALINSPIRALH_MSGEMEM);
00207           else
00208             ABORTXLAL( status );
00209         }
00210 
00211         /* Pad the first nStartPad elements of the signal array with zero */
00212         count = 0;
00213         while ((INT4)count < in->nStartPad)
00214         {
00215                 signal->data[count] = 0.L;
00216                 count++;
00217         }
00218 
00219         /* Get the initial conditions before the evolution */
00220         t = 0.L;                                                 /* initial time */
00221         dt = 1.L/in->tSampling;                                  /* Sampling interval */
00222         etaBy5M = in->eta/(5.L*acstPars.M);                      /* Constant that appears in ... */
00223         Theta = etaBy5M * (in->tC - t);                          /* ... Theta */
00224         tMax = in->tC - dt;                                      /* Maximum duration of the signal */
00225         fn = (ak.flso > in->fCutoff) ? ak.flso : in->fCutoff;    /* Frequency cutoff, smaller of user given f or flso */
00226   
00227         func.phasing3(status->statusPtr, &Phi, Theta, &ak);      /* Carrier phase at the initial time */
00228         CHECKSTATUSPTR(status);
00229         func.frequency3(status->statusPtr, &f, Theta, &ak);      /* Carrier Freqeuncy at the initial time */
00230         CHECKSTATUSPTR(status);
00231 
00232         /* Constants that appear in the antenna pattern */
00233         Fp0 = (1.L + cos(in->sourceTheta)*cos(in->sourceTheta)) * cos(2.L*in->sourcePhi); 
00234         Fp1 = cos(in->sourceTheta) * sin(2.L*in->sourcePhi);
00235         Fc0 = Fp0;
00236         Fc1 = -Fp1;
00237 
00238         psiOld = 0.L;
00239         phiOld = 0.L;
00240         magL = sqrt(values.data[0]*values.data[0] + values.data[1]*values.data[1] + values.data[2]*values.data[2]);
00241         NCapDotL = acstPars.NCap[0]*values.data[0] + acstPars.NCap[1]*values.data[1] + acstPars.NCap[2]*values.data[2];
00242         NCapDotLByL = NCapDotL/magL;
00243 
00244         /* Initial values of */
00245         /* the polarization angle */
00246         LALInspiralPolarisationAngle(&psi, psiOld, &acstPars.NCap[0], &values.data[0]);
00247         /* beam pattern factors */
00248         LALInspiralBeamFactors(&Fplus, &Fcross, Fp0, Fp1, Fc0, Fc1, psi);
00249         /* the polarization phase */
00250         LALInspiralPolarisationPhase(&phi, phiOld, NCapDotLByL, Fplus, Fcross);
00251         /* modulated amplitude */
00252         LALInspiralModulatedAmplitude(&amp, v, amp0, NCapDotLByL, Fplus, Fcross);
00253 
00254         phase = Phi + phi;
00255         phi0 = -phase + in->startPhase;
00256 
00257         fOld = f - 0.1;
00258         while (f < fn && t < tMax && f>fOld)
00259         {
00260                 ASSERT((INT4)count < (INT4)signal->length, status, LALINSPIRALH_ESIZE, LALINSPIRALH_MSGESIZE);
00261                 /* Subtract the constant initial phase (chosen to have a phase of in->startPhase) */
00262                 signal->data[count] = amp*cos(phase+phi0);
00263 
00264                 /*
00265                 double s1;
00266                 s1 = pow(pow(values.data[3],2.0) + pow(values.data[4], 2.0) +pow(values.data[5], 2.0), 0.5);
00267                 printf("%e %e %e %e %e\n", t, values.data[3], values.data[4], values.data[5], s1);
00268                 printf("%e %e %e %e %e %e %e %e\n", t, signal->data[count], Phi, phi, psi, NCapDotL/magL, Fcross, Fplus);
00269                 */
00270 
00271                 /* Record the old values of frequency, polarisation angle and phase */
00272                 fOld = f;
00273                 psiOld = psi;
00274                 phiOld = phi;
00275 
00276                 count++;
00277                 t = (count-in->nStartPad) * dt;
00278         
00279                 /* The velocity parameter */
00280                 acstPars.v = v;
00281                 /* Cast the input structure into a void struct as required by the RungeKutta4 routine */
00282                 funcParams = (void *) &acstPars;
00283                 /* Compute the derivatives at the current time. */
00284                 LALACSTDerivatives(&values, &dvalues, funcParams);
00285                 /* Supply the integration routine with derivatives and current time*/
00286                 rk4in.dydx = &dvalues;
00287                 rk4in.x = t;
00288                 /* Compute the carrier phase of the signal at the current time */
00289                 Theta = etaBy5M * (in->tC - t);
00290                 func.phasing3(status->statusPtr, &Phi, Theta, &ak);
00291                 CHECKSTATUSPTR(status);
00292                 /* Compute the post-Newtonian frequency of the signal and 'velocity' at the current time */
00293                 func.frequency3(status->statusPtr, &f, Theta, &ak);
00294                 CHECKSTATUSPTR(status);
00295                 v = pow(LAL_PI * in->totalMass * LAL_MTSUN_SI * f, 1.L/3.L);
00296                 /* Integrate the equations one step forward */
00297                 LALRungeKutta4(status->statusPtr, &newvalues, integrator, funcParams);
00298                 CHECKSTATUSPTR(status);
00299 
00300                 /* re-record the new values of the variables */
00301                 for (j=0; j<nDEDim; j++) values.data[j] = newvalues.data[j];
00302 
00303                 /* Compute the magnitude of the angular-momentum and its component along line-of-sight. */
00304                 magL = sqrt(values.data[0]*values.data[0] + values.data[1]*values.data[1] + values.data[2]*values.data[2]);
00305                 NCapDotL = acstPars.NCap[0]*values.data[0]+acstPars.NCap[1]*values.data[1]+acstPars.NCap[2]*values.data[2];
00306                 NCapDotLByL = NCapDotL/magL;
00307 
00308                 /* Compute the polarisation angle, beam factors, polarisation phase and modulated amplitude */
00309                 LALInspiralPolarisationAngle(&psi, psiOld, &acstPars.NCap[0], &values.data[0]);
00310                 LALInspiralBeamFactors(&Fplus, &Fcross, Fp0, Fp1, Fc0, Fc1, psi);
00311                 LALInspiralPolarisationPhase(&phi, phiOld, NCapDotLByL, Fplus, Fcross);
00312                 LALInspiralModulatedAmplitude(&amp, v, amp0, NCapDotLByL, Fplus, Fcross);
00313 
00314                 /* The new phase of the signal is ... */
00315                 phase = Phi + phi;
00316         }
00317         while (count < signal->length)
00318         {
00319                 signal->data[count] = 0.L;
00320                 count++;
00321         }
00322         XLALRungeKutta4Free( integrator );
00323         LALFree(dummy.data);
00324         DETATCHSTATUSPTR(status);
00325         RETURN(status);
00326 
00327 }
00328 
00329 
00330 static void 
00331 LALInspiralPolarisationAngle(
00332                 REAL8 *psi,
00333                 REAL8 psiOld,
00334                 REAL8 *NCap,
00335                 REAL8 *L)
00336 {
00337         REAL8 NCapDotL, NCapDotZ, LCapDotZ, NCapDotLCrossZ;
00338 
00339         /* page 6278, Eq. (20) of ACST */
00340         NCapDotL = NCap[0]*L[0] + NCap[1]*L[1] + NCap[2]*L[2];
00341         NCapDotZ = NCap[2];
00342         LCapDotZ = L[2];
00343         NCapDotLCrossZ = NCap[0]*L[1] - NCap[1]*L[0];
00344         if (NCapDotLCrossZ)
00345                 *psi = atan((LCapDotZ - NCapDotL*NCapDotZ)/NCapDotLCrossZ);
00346         else
00347                 *psi = LAL_PI_2;
00348 
00349         /* If you require your polarisation angle to be continuous, then uncomment the line below */
00350         if (psiOld) while (fabs(*psi-psiOld)>LAL_PI_2) *psi = (psiOld > *psi) ? *psi+LAL_PI : *psi-LAL_PI;
00351 }
00352 
00353 static void 
00354 LALInspiralBeamFactors(
00355                 REAL8 *Fplus, 
00356                 REAL8 *Fcross, 
00357                 REAL8 Fp0,
00358                 REAL8 Fp1,
00359                 REAL8 Fc0,
00360                 REAL8 Fc1,
00361                 REAL8 psi) 
00362 {
00363 
00364 
00365         REAL8 cosTwoPsi, sinTwoPsi;
00366         /* page 6276, Eqs. (4a) and (4b) of ACST */
00367 
00368         cosTwoPsi = cos(2.L*psi);
00369         sinTwoPsi = sin(2.L*psi);
00370 
00371         *Fplus = Fp0 * cosTwoPsi + Fp1 * sinTwoPsi;
00372         *Fcross = Fc0 * sinTwoPsi + Fc1 * cosTwoPsi;
00373 }
00374 
00375 static void 
00376 LALInspiralPolarisationPhase(
00377                 REAL8 *phi,
00378                 REAL8 phiOld,
00379                 REAL8 NCapDotLByL, 
00380                 REAL8 Fplus, 
00381                 REAL8 Fcross
00382                 ) 
00383 {
00384         /* page 6278, Eqs. (19b) of ACST */
00385         *phi=atan(2.L*NCapDotLByL*Fcross/((1.L + NCapDotLByL*NCapDotLByL)*Fplus));
00386 
00387         /* If you require your polarisation phase to be continuous, then uncomment the line below */
00388         if (phiOld) while (fabs(*phi-phiOld)>LAL_PI_2) *phi = (phiOld>*phi) ? *phi+LAL_PI : *phi-LAL_PI;
00389 }
00390 
00391 static void 
00392 LALInspiralModulatedAmplitude(
00393                 REAL8 *amp,
00394                 REAL8 v,
00395                 REAL8 amp0,
00396                 REAL8 NCapDotL,
00397                 REAL8 Fplus,
00398                 REAL8 Fcross
00399                 )
00400 {
00401         REAL8 NCapDotLSq;
00402         /* page 6278, Eqs. (19a) of ACST */
00403         NCapDotLSq = NCapDotL * NCapDotL;
00404         *amp = amp0 * v*v * sqrt ( pow(1.L+NCapDotLSq,2.L) * Fplus*Fplus + 4.L*NCapDotLSq*Fcross*Fcross);
00405 }
00406 
00407 /* computes the derivatives of the angular mom precession eqns for rkdumb */
00408 void 
00409 LALACSTDerivatives 
00410 (
00411  REAL8Vector *values,
00412  REAL8Vector *dvalues,
00413  void *funcParams
00414  )
00415 {
00416 
00417 
00418         /* derivatives of vectors L,S1,S2 */
00419         /* page 6277, Eqs. (11a)-(11c) of ACST 
00420          * Note that ACST has a mis-print in Eq. (11b) */
00421         /* loop variables */
00422         enum { Dim=3 };
00423         UINT4 i, j, k, p, q;             
00424         /* magnitudes of S1, S2, L etc. */
00425         REAL8 /*Theta,*/ v, M, magS1, magS2, magL, S1DotL, S2DotL;
00426         REAL8 fourM1Plus, fourM2Plus, oneBy2Mcube, Lsq, dL0, c2, v6;
00427         REAL8 L[Dim], S1[Dim], S2[Dim], S1CrossL[Dim], S2CrossL[Dim], S1CrossS2[Dim];   
00428         InspiralACSTParams *ACSTIn;
00429 
00430 
00431         ACSTIn = (InspiralACSTParams *) funcParams;
00432         /* extract 'velocity' and masses */
00433         v = ACSTIn->v;
00434         M = ACSTIn->M;
00435         magS1 = ACSTIn->magS1;
00436         magS2 = ACSTIn->magS2;
00437         fourM1Plus = ACSTIn->fourM1Plus;
00438         fourM2Plus = ACSTIn->fourM2Plus;
00439         oneBy2Mcube = ACSTIn->oneBy2Mcube;
00440         magL = sqrt(values->data[0]*values->data[0] + values->data[1]*values->data[1] + values->data[2]*values->data[2]);
00441 
00442         /* extract vectors, angular momentum and spins */
00443         for (i=0; i<Dim; i++)
00444         {
00445                 L[i]=values->data[i];
00446                 S1[i]=values->data[i+Dim];
00447                 S2[i]=values->data[i+2*Dim];
00448         }
00449 
00450         S1DotL = S2DotL = 0.L;
00451         for (i=0; i<Dim; i++)
00452         {
00453                 j = (i+1) % Dim;
00454                 k = (i+2) % Dim;
00455                 S1DotL += S1[i] * L[i];
00456                 S2DotL += S2[i] * L[i];
00457                 S1CrossL[i] = S1[j] * L[k] - S1[k] * L[j];
00458                 S2CrossL[i] = S2[j] * L[k] - S2[k] * L[j];
00459                 S1CrossS2[i] = S1[j] * S2[k] - S1[k] * S2[j];
00460         }
00461 
00462 
00463         Lsq = magL*magL;
00464         dL0 = ACSTIn->thirtytwoBy5etc/magL;
00465         c2 = ACSTIn->threeBy2Mcube/Lsq;
00466         v6 = pow(v,6.L);
00467 
00468         /*
00469         printf("%e %e %e\n", L[0], L[1], L[2]);
00470         printf("%e %e %e\n", S1[0], S1[1], S1[2]);
00471         printf("%e %e %e\n", S2[0], S2[1], S2[2]);
00472         printf("%e %e %e\n", S1CrossS2[0], S1CrossS2[1], S1CrossS2[2]);
00473         printf("%e %e %e\n", S1CrossL[0], S1CrossL[1], S1CrossL[2]);
00474         printf("%e %e %e %e %e %e\n", S1DotL, S2DotL, Lsq, dL0, c2, v6);
00475         */
00476                 
00477         for(i=0;i<Dim;i++) 
00478         {
00479                 p = i+Dim;
00480                 q = i+2*Dim;
00481                 /* compute the derivatives */
00482                 dvalues->data[i] = ((fourM1Plus - c2 * S2DotL) * S1CrossL[i]
00483                       +  (fourM2Plus - c2 * S1DotL) * S2CrossL[i] - dL0 * L[i]*v) * v6;;
00484                 
00485                 dvalues->data[p] = ((c2 * S2DotL - fourM1Plus) * S1CrossL[i] - oneBy2Mcube * S1CrossS2[i]) * v6;
00486 
00487                 dvalues->data[q] = ((c2 * S1DotL - fourM2Plus) * S2CrossL[i] + oneBy2Mcube * S1CrossS2[i]) * v6;
00488         }                                        
00489 
00490 }
00491 
00492 
00493 
00494 /* Routine to inject inspiral waveforms from binaries consisting of spinning objects */
00495 /*  <lalVerbatim file="LALInspiralSpinningBHBinaryCP"> */
00496 
00497 /* NOT DONE FOR THE MOMENT should remove the polarisation effects which are already 
00498    taken into account in inject package */
00499 void 
00500 LALInspiralSpinModulatedWaveForInjection(
00501                                          LALStatus        *status,
00502                                          CoherentGW *waveform,
00503                                          InspiralTemplate *params,
00504                                          PPNParamStruc  *ppnParams      
00505                                          )
00506 { /* </lalVerbatim> */
00507   
00508   
00509   UINT4 nDEDim=9/*, Dim=3*/;
00510   UINT4 i,j, count, length = 0;
00511   /* polarisation and antenna pattern */
00512   REAL8 omega,psi, psiOld, Fplus, Fcross, Fp0, Fp1, Fc0, Fc1, magL, amp, amp0, phi, phiOld, /*Amplitude,*/ Phi/*, dPhi*/;
00513   REAL8 v, t, tMax, dt, f, fOld, fn, phase, phi0, MCube, Theta, etaBy5M, NCapDotL, NCapDotLByL;
00514   /* source direction angles */
00515   InspiralACSTParams acstPars;
00516   REAL8Vector dummy, values, dvalues, newvalues, yt, dym, dyt;
00517   void *funcParams;
00518     rk4In rk4in;
00519     rk4GSLIntegrator *integrator;
00520     expnFunc func;
00521     expnCoeffs ak;
00522     REAL4Vector *a=NULL;
00523     REAL4Vector *ff=NULL ;
00524     REAL8Vector *phiv=NULL;
00525     REAL8 unitHz,f2a, mu, mTot, cosI, etab, fFac,  f2aFac, apFac, acFac, phiC;
00526     CreateVectorSequenceIn in;
00527 
00528     mTot   =  params->mass1 + params->mass2;
00529     etab   =  params->mass1 * params->mass2;
00530     etab  /= mTot;
00531     etab  /= mTot;
00532     unitHz = (mTot) *LAL_MTSUN_SI*(REAL8)LAL_PI;
00533     cosI   = cos( params->inclination );
00534     mu     = etab * mTot;  
00535     fFac   = 1.0 / ( 4.0*LAL_TWOPI*LAL_MTSUN_SI*mTot );
00536     dt     = -1. * etab / ( params->tSampling * 5.0*LAL_MTSUN_SI*mTot );      
00537     f2aFac = LAL_PI*LAL_MTSUN_SI*mTot*fFac;   
00538     apFac  = acFac = -2.0 * mu * LAL_MRSUN_SI/params->distance;
00539     apFac *= 1.0 + cosI*cosI;
00540     acFac *= 2.0*cosI;
00541     
00542 
00543     INITSTATUS(status, "LALInspiralSpinngBHBinaryForInjection", LALINSPIRALSPINNINGBHBINARYC);
00544     ATTATCHSTATUSPTR(status);
00545     ASSERT(params,  status, LALINSPIRALH_ENULL, LALINSPIRALH_MSGENULL);
00546     /* Make sure waveform fields don't exist. */
00547     ASSERT( !( waveform->a ), status, LALINSPIRALH_ENULL,
00548             LALINSPIRALH_MSGENULL );
00549     ASSERT( !( waveform->f ), status, LALINSPIRALH_ENULL,
00550             LALINSPIRALH_MSGENULL );
00551     ASSERT( !( waveform->phi ), status, LALINSPIRALH_ENULL,
00552             LALINSPIRALH_MSGENULL );
00553     ASSERT( !( waveform->shift ), status, LALINSPIRALH_ENULL,
00554             LALINSPIRALH_MSGENULL );
00555     
00556 
00557     LALInspiralSetup (status->statusPtr, &ak, params);
00558     CHECKSTATUSPTR(status);
00559     LALInspiralChooseModel(status->statusPtr, &func, &ak, params);
00560     CHECKSTATUSPTR(status);
00561     LALInspiralWaveLength(status->statusPtr, &length, *params);
00562     CHECKSTATUSPTR(status);
00563     LALInspiralParameterCalc(status->statusPtr, params);
00564     CHECKSTATUSPTR(status);
00565 
00566     /* memset(&ff,0,sizeof(REAL4TimeSeries));*/
00567     LALSCreateVector(status->statusPtr, &ff, length);
00568     CHECKSTATUSPTR(status);
00569     
00570     LALSCreateVector(status->statusPtr, &a, 2*length);
00571     CHECKSTATUSPTR(status);
00572     
00573     LALDCreateVector(status->statusPtr, &phiv, length);
00574     CHECKSTATUSPTR(status);
00575   
00576 
00577     /* Allocate space for all the vectors in one go ... */
00578     
00579     dummy.length = nDEDim * 6;
00580     values.length = dvalues.length = newvalues.length = yt.length = dym.length = dyt.length = nDEDim;
00581     
00582     if (!(dummy.data = (REAL8 *) LALMalloc(sizeof(REAL8) * dummy.length))) 
00583       {
00584         ABORT(status, LALINSPIRALH_EMEM, LALINSPIRALH_MSGEMEM);
00585       }
00586     
00587     /* and distribute as necessary */
00588     values.data = &dummy.data[0];             /* values of L, S1, S2 at current time */
00589     dvalues.data = &dummy.data[nDEDim];       /* values of dL/dt, dS1/dt, dS2/dt at current time */
00590     newvalues.data = &dummy.data[2*nDEDim];   /* new values of L, S1, S2 after time increment by dt*/
00591     yt.data = &dummy.data[3*nDEDim];          /* Vector space needed by LALRungeKutta4 */
00592     dym.data = &dummy.data[4*nDEDim];         /* Vector space needed by LALRungeKutta4 */
00593     dyt.data = &dummy.data[5*nDEDim];         /* Vector space needed by LALRungeKutta4 */
00594     
00595     v = pow(LAL_PI * params->totalMass * LAL_MTSUN_SI * params->fLower, 1.L/3.L);
00596     MCube = pow(LAL_MTSUN_SI * params->totalMass, 3.L);
00597     /* Fill in the structure needed by the routine that computes the derivatives */
00598     /* constant spins of the two bodies */
00599     acstPars.magS1 = params->spin1[0]*params->spin1[0] + params->spin1[1]*params->spin1[1] + params->spin1[2]*params->spin1[2];
00600     acstPars.magS2 = params->spin2[0]*params->spin2[0] + params->spin2[1]*params->spin2[1] + params->spin2[2]*params->spin2[2];
00601     /* Direction to the source in the solar system barycenter */
00602     acstPars.NCap[0] = sin(params->sourceTheta)*cos(params->sourcePhi);
00603     acstPars.NCap[1] = sin(params->sourceTheta)*sin(params->sourcePhi);
00604     acstPars.NCap[2] = cos(params->sourceTheta);
00605     /* total mass in seconds */
00606     acstPars.M = LAL_MTSUN_SI * params->totalMass;
00607     /* Combination of masses that appears in the evolution of L, S1 and S2 */
00608     acstPars.fourM1Plus = (4.L*params->mass1 + 3.L*params->mass2)/(2.*params->mass1*MCube);
00609     acstPars.fourM2Plus = (4.L*params->mass2 + 3.L*params->mass1)/(2.*params->mass2*MCube);
00610     acstPars.oneBy2Mcube = 0.5L/MCube;
00611     acstPars.threeBy2Mcube = 1.5L/MCube;
00612     acstPars.thirtytwoBy5etc = (32.L/5.L) * pow(params->eta,2.) * acstPars.M;
00613     
00614     /* Constant amplitude of GW */
00615     amp0 = 2.L*params->eta * acstPars.M/params->distance;
00616     /* Initial magnitude of the angular momentum, determined by the initial frequency/velocity */
00617     magL = params->eta * (acstPars.M * acstPars.M)/v;
00618     /* Initial angular momentum and spin vectors */
00619     /* Angular momentum */
00620     values.data[0] = magL * sin(params->orbitTheta0) * cos(params->orbitPhi0);
00621     values.data[1] = magL * sin(params->orbitTheta0) * sin(params->orbitPhi0);
00622     values.data[2] = magL * cos(params->orbitTheta0);
00623     /* Spin of primary */
00624     values.data[3] = params->spin1[0];
00625     values.data[4] = params->spin1[1];
00626     values.data[5] = params->spin1[2];
00627     /* Spin of secondarfy */
00628     values.data[6] = params->spin2[0];
00629     values.data[7] = params->spin2[1];
00630     values.data[8] = params->spin2[2];
00631     /* Structure needed by RungeKutta4 for the evolution of the differential equations */
00632     rk4in.function = LALACSTDerivatives;
00633     rk4in.y = &values;
00634     rk4in.h = 1.L/params->tSampling;
00635     rk4in.n = nDEDim;
00636     rk4in.yt = &yt;
00637     rk4in.dym = &dym;
00638     rk4in.dyt = &dyt;
00639 
00640     xlalErrno = 0;
00641     /* Initialize GSL integrator */
00642     if (!(integrator = XLALRungeKutta4Init(nDEDim, &rk4in)))
00643     {
00644       INT4 errNum = XLALClearErrno();
00645       LALFree(dummy.data);
00646 
00647       if (errNum = XLAL_ENOMEM)
00648         ABORT(status, LALINSPIRALH_EMEM, LALINSPIRALH_MSGEMEM);
00649       else
00650         ABORTXLAL( status );
00651     }
00652     
00653     /* Pad the first nStartPad elements of the signal array with zero */
00654     count = 0;
00655     
00656 
00657     /* Get the initial conditions before the evolution */
00658     t = 0.L;                                                 /* initial time */
00659     dt = 1.L/params->tSampling;                                  /* Sampling interval */
00660     etaBy5M = params->eta/(5.L*acstPars.M);                      /* Constant that appears in ... */
00661     Theta = etaBy5M * (params->tC - t);                          /* ... Theta */
00662     tMax = params->tC - dt;                                      /* Maximum duration of the signal */
00663     fn = (ak.flso > params->fCutoff) ? ak.flso : params->fCutoff;    /* Frequency cutoff, smaller of user given f or flso */
00664     
00665     func.phasing3(status->statusPtr, &Phi, Theta, &ak);      /* Carrier phase at the initial time */
00666     CHECKSTATUSPTR(status);
00667     func.frequency3(status->statusPtr, &f, Theta, &ak);      /* Carrier Freqeuncy at the initial time */
00668     CHECKSTATUSPTR(status);
00669     
00670     /* Constants that appear in the antenna pattern */
00671     Fp0 = (1.L + cos(params->sourceTheta)*cos(params->sourceTheta)) * cos(2.L*params->sourcePhi); 
00672     Fp1 = cos(params->sourceTheta) * sin(2.L*params->sourcePhi);
00673     Fc0 = Fp0;
00674     Fc1 = -Fp1;
00675     
00676     psiOld = 0.L;
00677     phiOld = 0.L;
00678     magL = sqrt(values.data[0]*values.data[0] + values.data[1]*values.data[1] + values.data[2]*values.data[2]);
00679     NCapDotL = acstPars.NCap[0]*values.data[0] + acstPars.NCap[1]*values.data[1] + acstPars.NCap[2]*values.data[2];
00680     NCapDotLByL = NCapDotL/magL;
00681 
00682     /* Initial values of */
00683     /* the polarization angle */
00684     LALInspiralPolarisationAngle(&psi, psiOld, &acstPars.NCap[0], &values.data[0]);
00685     /* beam pattern factors */
00686     LALInspiralBeamFactors(&Fplus, &Fcross, Fp0, Fp1, Fc0, Fc1, psi);
00687     /* the polarization phase */
00688     LALInspiralPolarisationPhase(&phi, phiOld, NCapDotLByL, Fplus, Fcross);
00689     /* modulated amplitude */
00690     LALInspiralModulatedAmplitude(&amp, v, amp0, NCapDotLByL, Fplus, Fcross);
00691     
00692 
00693     phase = Phi + phi;
00694     phi0 = -phase + params->startPhase;
00695     
00696     fOld = f - 0.1;
00697     while (f < fn && t < tMax && f>fOld)
00698       {
00699         /*ASSERT((INT4)count < (INT4)signal->length, status, LALINSPIRALH_ESIZE, LALINSPIRALH_MSGESIZE);*/
00700         /* Subtract the constant initial phase (chosen to have a phase of in->startPhase) */
00701 
00702 
00703 
00704         omega = v*v*v;
00705         ff->data[count]= (REAL4)(omega/unitHz);
00706         f2a = pow (f2aFac * omega, 2./3.);
00707         a->data[2*count]          = (REAL4)(4.*apFac * f2a);
00708         a->data[2*count+1]        = (REAL4)(4.*acFac * f2a);
00709         phiv->data[count]          = (REAL8)(phase);
00710 
00711 
00712         
00713         /*
00714           double s1;
00715           s1 = pow(pow(values.data[3],2.0) + pow(values.data[4], 2.0) +pow(values.data[5], 2.0), 0.5);
00716           printf("%e %e %e %e %e\n", t, values.data[3], values.data[4], values.data[5], s1);
00717           printf("%e %e %e %e %e %e %e %e\n", t, signal->data[count], Phi, phi, psi, NCapDotL/magL, Fcross, Fplus);
00718         */
00719         
00720         /* Record the old values of frequency, polarisation angle and phase */
00721         fOld = f;
00722         psiOld = psi;
00723         phiOld = phi;
00724         
00725         count++;
00726         t = (count-params->nStartPad) * dt;
00727         
00728         /* The velocity parameter */
00729         acstPars.v = v;
00730         /* Cast the input structure into a void struct as required by the RungeKutta4 routine */
00731         funcParams = (void *) &acstPars;
00732         /* Compute the derivatives at the current time. */
00733         LALACSTDerivatives(&values, &dvalues, funcParams);
00734         /* Supply the integration routine with derivatives and current time*/
00735         rk4in.dydx = &dvalues;
00736         rk4in.x = t;
00737         /* Compute the carrier phase of the signal at the current time */
00738         Theta = etaBy5M * (params->tC - t);
00739         func.phasing3(status->statusPtr, &Phi, Theta, &ak);
00740         CHECKSTATUSPTR(status);
00741         /* Compute the post-Newtonian frequency of the signal and 'velocity' at the current time */
00742         func.frequency3(status->statusPtr, &f, Theta, &ak);
00743         CHECKSTATUSPTR(status);
00744         v = pow(LAL_PI * params->totalMass * LAL_MTSUN_SI * f, 1.L/3.L);
00745         /* Integrate the equations one step forward */
00746         LALRungeKutta4(status->statusPtr, &newvalues, integrator, funcParams);
00747         CHECKSTATUSPTR(status);
00748         
00749         /* re-record the new values of the variables */
00750         for (j=0; j<nDEDim; j++) values.data[j] = newvalues.data[j];
00751         
00752         /* Compute the magnitude of the angular-momentum and its component along line-of-sight. */
00753         magL = sqrt(values.data[0]*values.data[0] + values.data[1]*values.data[1] + values.data[2]*values.data[2]);
00754         NCapDotL = acstPars.NCap[0]*values.data[0]+acstPars.NCap[1]*values.data[1]+acstPars.NCap[2]*values.data[2];
00755         NCapDotLByL = NCapDotL/magL;
00756         
00757         /* Compute the polarisation angle, beam factors, polarisation phase and modulated amplitude */
00758         LALInspiralPolarisationAngle(&psi, psiOld, &acstPars.NCap[0], &values.data[0]);
00759         LALInspiralBeamFactors(&Fplus, &Fcross, Fp0, Fp1, Fc0, Fc1, psi);
00760         LALInspiralPolarisationPhase(&phi, phiOld, NCapDotLByL, Fplus, Fcross);
00761         LALInspiralModulatedAmplitude(&amp, v, amp0, NCapDotLByL, Fplus, Fcross);
00762         
00763         /* The new phase of the signal is ... */
00764         phase = Phi + phi;
00765       }
00766 
00767 
00768