BinaryPulsarTiming.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Jolien Creighton, Matt Pitkin, Reinhard Prix
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 /**
00021  * \author Matt Pitkin, Reinhard Prix
00022  * \date 2006
00023  * \file
00024  * \ingroup pulsar
00025  * \brief Functions to calculate binary system time delays and read TEMPO pulsar parameter files
00026  *
00027  * $Id: BinaryPulsarTiming.c,v 1.22 2008/04/21 17:48:47 mpitkin Exp $
00028  *
00029  */
00030 
00031 /* LAL functions to calculate the timing differences needed to
00032    take into account binary pulsar orbits
00033    Models are taken from Taylor and Weisberg (1989) and use the
00034    naming conventions therein and used by TEMPO */
00035    
00036 /*   Also contains function to read TEMPO .par files to obtain parameters
00037   and errors on parameters (if available) */
00038 
00039 /* <lalVerbatim file="BinaryPulsarTimingCV">
00040    Author: Pitkin, M. D.
00041    $Id: BinaryPulsarTiming.c,v 1.22 2008/04/21 17:48:47 mpitkin Exp $
00042    </lalVerbatim>
00043    
00044    <lalLaTeX>
00045    \subsection{Module \texttt{BinaryPulsarTiming.c}}
00046    \label{ss:BinaryPulsarTiming.c}
00047    
00048    Functions for calculating the timing delay to a signal from a pulsar in a
00049    binary system and reading pulsar parameters from TEMPO \cite{TEMPO} .par
00050    files.
00051    
00052    \subsubsection*{Prototypes}
00053    \vspace{0.1in}
00054    \input{BinaryPulsarTimingCP}
00055    \idx{LALBinaryPulsarDeltaT()}
00056    \idx{LALReadTEMPOParFile()}
00057    \idx{LALdegsToRads()}
00058    
00059    \subsubsection*{Description}
00060    
00061    The main function computes the time delay of a signal from a pulsar in a
00062    binary system due to doppler shifts and relativistic delays, 
00063    \begin{equation}
00064    \Delta{}t = t_{\rm Roemer} + t_{\rm Shapiro} + t_{\rm Einstein} + t_{\rm
00065    Abberation},
00066    \end{equation}
00067    where $t_{\rm Roemer}$ is the light travel time, $t_{\rm Shapiro}$ is the
00068    General relativistic time delay, $t_{\rm Einstein}$ is the special
00069    relativistic time delay, and $t_{\rm Abberation}$ is the delay caused by the
00070    pulsars' rotation. There are several models of the binary systems, described 
00071    in \cite{TaylorWeisberg:1989}, of which the four most common are so far
00072    implemented. The four models are the Blandford-Teukolsky model (BT)
00073    \cite{BlandfordTeukolsky:1976}, the low ellipticity model (ELL1)
00074    \cite{ChLangeetal:2001}, Damour-Deruelle model (DD) \cite{DamourDeruelle:1985}, 
00075    and the main sequence system model (MSS) \cite{Wex:1998}.
00076    These four models all use the five main binary parameters: the longitude of
00077    periastron $\omega_0$, the eccentricity of the orbit $e$, the orbital period
00078    $P$, the time of periastron/or the time of ascension of the first node 
00079    $T_0$/$T_{{\rm asc}}$, and the projected semi-major axis $a\sin{}i$. The are
00080    also many other model dependent parameters. These routines closely follow
00081    those used in the radio astronomy package TEMPO \cite{TEMPO}.
00082  
00083    Radio astronomers fit pulsar parameters using TEMPO which will output
00084    the parameters in a \verb+.par+ file. The values allowed in this file can be
00085    found in the TEMPO documentation. A function is included to extract these 
00086    parameters from the \verb+.par+ files and put them into a
00087    \verb+BinaryPulsarParams+ structure, it will set any unused parameters to
00088    zero or \texttt{NULL}. All parameters are in the units used by TEMPO with any
00089    conversion to SI units occuring within the binary timing routines. A function
00090    is also included which converts a string containing the right ascension or 
00091    declination in the format \texttt{ddd/hh:mm:ss.s} or \texttt{ddd/hhmmss.s} 
00092    (as is given in the \texttt{.par} file) into a \texttt{REAL8} value in 
00093    radians.
00094  
00095    \subsubsection*{Notes}
00096    
00097    \vfill{\footnotesize\input{BinaryPulsarTimingCV}}
00098    
00099    </lalLaTeX>
00100 */
00101 
00102 /* Matt Pitkin 29/04/04 */
00103 
00104 #include <lal/BinaryPulsarTiming.h>
00105 
00106 #include <string.h>
00107 #include <math.h>
00108 #include <lal/LALConstants.h>
00109 #include <lal/LALStdlib.h>
00110 #include <lal/LALString.h>
00111 
00112 #define DAYSTOSECS 86400.0 /* number of seconds in a day */
00113 
00114 /******* DEFINE RCS ID STRING ************/
00115 NRCSID( BINARYPULSARTIMINGC, "$Id: BinaryPulsarTiming.c,v 1.22 2008/04/21 17:48:47 mpitkin Exp $" );
00116 
00117 /** Calculate the binary system time delay using the pulsar parameters in 
00118  *  \c params
00119  */
00120 void
00121 LALBinaryPulsarDeltaT( LALStatus            *status,
00122                        BinaryPulsarOutput   *output,
00123                        BinaryPulsarInput    *input,
00124                        BinaryPulsarParams   *params ){
00125   INITSTATUS(status, "LALBinaryPulsarDeltaT", BINARYPULSARTIMINGC);
00126   ATTATCHSTATUSPTR(status);
00127 
00128   /* Check input arguments */
00129   ASSERT(input != (BinaryPulsarInput *)NULL, status, 
00130   BINARYPULSARTIMINGH_ENULLINPUT, BINARYPULSARTIMINGH_MSGENULLINPUT);
00131 
00132   ASSERT(output != (BinaryPulsarOutput *)NULL, status, 
00133   BINARYPULSARTIMINGH_ENULLOUTPUT, BINARYPULSARTIMINGH_MSGENULLOUTPUT);
00134 
00135   ASSERT(params != (BinaryPulsarParams *)NULL, status, 
00136   BINARYPULSARTIMINGH_ENULLPARAMS, BINARYPULSARTIMINGH_MSGENULLPARAMS);
00137 
00138   ASSERT((!strcmp(params->model, "BT")) ||
00139          (!strcmp(params->model, "BT1P")) ||
00140          (!strcmp(params->model, "BT2P")) ||
00141          (!strcmp(params->model, "BTX")) ||
00142          (!strcmp(params->model, "ELL1")) ||
00143          (!strcmp(params->model, "DD")) ||
00144          (!strcmp(params->model, "MSS")), status,
00145          BINARYPULSARTIMINGH_ENULLBINARYMODEL, 
00146          BINARYPULSARTIMINGH_MSGNULLBINARYMODEL);
00147 
00148   XLALBinaryPulsarDeltaT( output, input, params );
00149 
00150   DETATCHSTATUSPTR(status);
00151   RETURN(status);
00152 }
00153 
00154 /** XLAL function to compute the binary time delay
00155   */
00156 void
00157 XLALBinaryPulsarDeltaT( BinaryPulsarOutput   *output,
00158                         BinaryPulsarInput    *input,
00159                         BinaryPulsarParams   *params )
00160 {
00161   const CHAR *fn = "XLALBinaryPulsarDeltaT()";
00162 
00163   REAL8 dt=0.; /* binary pulsar deltaT */
00164   REAL8 x, xdot;        /* x = asini/c */
00165   REAL8 w;  /* longitude of periastron */
00166   REAL8 e, edot;  /* eccentricity */
00167   REAL8 eps1, eps2;
00168   REAL8 eps1dot, eps2dot;
00169   REAL8 w0, wdot;
00170   REAL8 Pb, pbdot;
00171   REAL8 xpbdot;
00172   REAL8 T0, Tasc, tb=0.; /* time parameters */
00173 
00174   REAL8 s, r; /* Shapiro shape and range params */
00175   REAL8 gamma; /* time dilation and grav redshift */
00176   REAL8 dr, dth;
00177 
00178   REAL8 a0, b0; /* abberation parameters */
00179   
00180   REAL8 M, m2;
00181   REAL8 c3 = (REAL8)LAL_C_SI*(REAL8)LAL_C_SI*(REAL8)LAL_C_SI;
00182   
00183   CHAR *model = params->model;
00184 
00185   /* Check input arguments */
00186   if( input == (BinaryPulsarInput *)NULL ){
00187     XLAL_ERROR_VOID( fn, BINARYPULSARTIMINGH_ENULLINPUT );
00188   }
00189 
00190   if( output == (BinaryPulsarOutput *)NULL ){
00191     XLAL_ERROR_VOID( fn, BINARYPULSARTIMINGH_ENULLOUTPUT );
00192   }
00193 
00194   if( params == (BinaryPulsarParams *)NULL ){
00195     XLAL_ERROR_VOID( fn, BINARYPULSARTIMINGH_ENULLPARAMS );
00196   }
00197 
00198   if((!strcmp(params->model, "BT")) &&
00199      (!strcmp(params->model, "BT1P")) &&
00200      (!strcmp(params->model, "BT2P")) &&
00201      (!strcmp(params->model, "BTX")) &&
00202      (!strcmp(params->model, "ELL1")) &&
00203      (!strcmp(params->model, "DD")) &&
00204      (!strcmp(params->model, "MSS"))){
00205     XLAL_ERROR_VOID( fn, BINARYPULSARTIMINGH_ENULLBINARYMODEL );
00206   }
00207 
00208   /* convert certain params to SI units */
00209   w0 = params->w0*LAL_PI_180; /* convert w to rads from degs */
00210   wdot = params->wdot*LAL_PI_180/(365.25*DAYSTOSECS); /* convert wdot to rads/s from degs/yr */
00211 
00212   Pb = params->Pb*DAYSTOSECS; /* covert period from days to secs */
00213   pbdot = params->Pbdot*1.0e-12;
00214   
00215   T0 = params->T0; /* these should be in TDB in seconds */
00216   Tasc = params->Tasc;  
00217 
00218   e = params->e;
00219   edot = params->edot*1.0e-12;
00220   eps1 = params->eps1;
00221   eps2 = params->eps2;
00222   eps1dot = params->eps1dot;
00223   eps2dot = params->eps2dot;
00224 
00225   x = params->x;
00226   xdot = params->xdot*1.0e-12;
00227   xpbdot = params->xpbdot*1.0e-12;
00228 
00229   gamma = params->gamma;
00230   s = params->s;
00231   dr = params->dr;
00232   dth = params->dth*1.0e-6;
00233 
00234   a0 = params->a0*1.0e-6; /* from microsecs to secs */
00235   b0 = params->b0*1.0e-6;
00236 
00237   M = params->M*LAL_MSUN_SI; /* from solar masses to kg */
00238   m2 = params->m2*LAL_MSUN_SI;
00239 
00240   /* Shapiro range parameter r defined as Gm2/c^3 (secs) */
00241   r = LAL_G_SI*m2/c3;
00242   
00243   /* if T0 is not defined, but Tasc is */
00244   if(T0 == 0.0 && Tasc != 0.0 && eps1 == 0.0 && eps2 == 0.0){
00245     REAL8 fe, uasc, Dt; /* see TEMPO tasc2t0.f */
00246 
00247     fe = sqrt((1.0 - e)/(1.0 + e));
00248     uasc = 2.0*atan(fe*tan(w0/2.0));
00249     Dt = (Pb/LAL_TWOPI)*(uasc-e*sin(uasc));
00250 
00251     T0 = Tasc + Dt;
00252   }
00253 
00254   /* set time at which to calculate the binary time delay */
00255   tb = input->tb;
00256   
00257   /* for BT, BT1P and BT2P models (and BTX model, but only for one orbit) */
00258   if(strstr(model, "BT") != NULL){
00259     REAL8 tt0;
00260     REAL8 orbits=0.; 
00261     INT4 norbits=0.;
00262     REAL8 phase; /* same as mean anomaly */
00263     REAL8 u = 0.0; /* eccentric anomaly */
00264     REAL8 du = 1.0; 
00265   
00266     INT4 nplanets=1; /* number of orbitting bodies in system */
00267     INT4 i=1, j=1;
00268     REAL8 fac=1.; /* factor in front of fb coefficients */  
00269 
00270     /* work out number of orbits i.e. have we got a BT1P or BT2P model */
00271     if(strstr(model, "BT1P") != NULL)
00272       nplanets = 2;
00273     if(strstr(model, "BT2P") != NULL)
00274       nplanets = 3;
00275 
00276     for ( i=1 ; i < nplanets+1 ; i++){
00277 
00278       /* set some vars for bnrybt.f (TEMPO) method */
00279       /*REAL8 tt;
00280       REAL8 som;
00281       REAL8 com;
00282       REAL8 alpha, beta;*/
00283       /*REAL8 q, r, s;*/
00284 
00285       /*fprintf(stderr, "You are using the Blandford-Teukolsky (BT) binary
00286         model.\n");*/           
00287 
00288       if(i==2){
00289         T0 = params->T02;
00290         w0 = params->w02*LAL_PI_180;
00291         x = params->x2;
00292         e = params->e2;
00293         Pb = params->Pb2*DAYSTOSECS;
00294       }
00295       else if(i==3){
00296         T0 = params->T03;
00297         w0 = params->w03*LAL_PI_180;
00298         x = params->x3;
00299         e = params->e3;
00300         Pb = params->Pb3*DAYSTOSECS;
00301       }
00302 
00303       tt0 = tb - T0;
00304 
00305       /* only do relativistic corrections for first orbit */
00306       if(i==1){
00307         x = x + xdot*tt0;
00308         e = e + edot*tt0;
00309         w = w0 + wdot*tt0; /* calculate w */
00310 
00311         if( strstr(model, "BTX") != NULL ){
00312           fac = 1.;
00313           for ( j=1 ; j < params->nfb + 1; j++){
00314             fac /= (REAL8)j;
00315             orbits += fac*params->fb[j-1]*pow(tt0,j);
00316           }
00317         }
00318         else{ 
00319           orbits = tt0/Pb - 0.5*(pbdot+xpbdot)*(tt0/Pb)*(tt0/Pb);
00320         }
00321       }
00322       else{
00323         orbits = tt0/Pb;
00324       }
00325 
00326       norbits = (INT4)floor(orbits);
00327 
00328       if(orbits < 0)
00329         norbits = norbits - 1;
00330 
00331       phase = LAL_TWOPI*(orbits - (REAL8)norbits); /* called phase in TEMPO */
00332       /*phase = LAL_TWOPI*(orbits);*/
00333       du = 1.0;
00334 
00335       /* use numerical iteration to solve Kepler's eq for eccentric anomaly u */
00336       u = phase + e*sin(phase)*(1.0 + e*cos(phase));
00337       while(fabs(du) > 1.0e-12){
00338         du = (phase-(u-e*sin(u)))/(1.0-e*cos(u));
00339         u += du;
00340       }
00341 
00342       /*fprintf(stderr, "Eccentric anomaly = %f, phase = %f.\n", u, phase);*/
00343     
00344       /* see eq 5 of Taylor and Weisberg (1989) */
00345       /**********************************************************/
00346       if( strstr(model, "BTX") != NULL ){
00347         dt += (x*sin(w)*(cos(u)-e) + (x*cos(w)*sqrt(1.0-e*e) +
00348           gamma)*sin(u))*(1.0 - params->fb[0]*(x*cos(w)*sqrt(1.0 -
00349           e*e)*cos(u) - x*sin(w)*sin(u))/(1.0 - e*cos(u)));
00350       }
00351       else{
00352         dt += (x*sin(w)*(cos(u)-e) + (x*cos(w)*sqrt(1.0-e*e) +
00353           gamma)*sin(u))*(1.0 - (LAL_TWOPI/Pb)*(x*cos(w)*sqrt(1.0 -
00354           e*e)*cos(u) - x*sin(w)*sin(u))/(1.0 - e*cos(u)));
00355       }
00356     /**********************************************************/
00357     }    
00358 
00359     /* use method from Taylor etal 1976 ApJ Lett and used in bnrybt.f */
00360     /**********************************************************/
00361     /*tt = 1.0-e*e;
00362     som = sin(w);
00363     com = cos(w);
00364     alpha = x*som;
00365     beta = x*com*sqrt(tt);
00366     q = alpha*(cos(u)-e) + (beta+gamma)*sin(u);
00367     r = -alpha*sin(u) + beta*cos(u);
00368     s = 1.0/(1.0-e*cos(u));
00369     dt = -(-q+(LAL_TWOPI/Pb)*q*r*s);*/
00370     /**********************************************************/
00371     /* There appears to be NO difference between either method */
00372 
00373     output->deltaT = -dt;
00374   }
00375 
00376   /* for ELL1 model (low eccentricity orbits so use eps1 and eps2) */
00377   /* see Appendix A, Ch. Lange etal, MNRAS (2001)                  */
00378   if(strstr(model, "ELL1") != NULL){
00379     REAL8 nb = LAL_TWOPI/Pb;
00380     REAL8 tt0;
00381     REAL8 w_int; /* omega internal to this model */
00382     REAL8 orbits, phase;
00383     INT4 norbits;
00384     REAL8 e1, e2, ecc;
00385     REAL8 DRE, DREp, DREpp; /* Roemer and Einstein delays (cf DD) */
00386     REAL8 dlogbr;
00387     REAL8 DS, DA; /* Shapiro delay and Abberation delay terms */
00388     REAL8 Dbb;
00389 
00390     /* fprintf(stderr, "You are using the ELL1 low eccentricity orbit model.\n");*/
00391 
00392     /*********************************************************/
00393     /* CORRECT CODE (as in TEMPO bnryell1.f) FROM HERE       */
00394 
00395     ecc = sqrt(eps1*eps1 + eps2*eps2);
00396 
00397     /* if Tasc is not defined convert T0 */
00398     if(Tasc == 0.0 && T0 != 0.0){
00399       REAL8 fe, uasc, Dt; /* see TEMPO tasc2t0.f */
00400 
00401       fe = sqrt((1.0 - ecc)/(1.0 + ecc));
00402       uasc = 2.0*atan(fe*tan(w0/2.0));
00403       Dt = (Pb/LAL_TWOPI)*(uasc-ecc*sin(uasc));
00404 
00405       /* rearrange from what's in tasc2t0.f */
00406       Tasc = T0 - Dt;
00407     }
00408 
00409     tt0 = tb - Tasc;
00410     orbits = tt0/Pb - 0.5*(pbdot+xpbdot)*(tt0/Pb)*(tt0/Pb);
00411     norbits = (INT4)floor(orbits);
00412     if(orbits < 0.0)
00413       norbits = norbits - 1.0;
00414 
00415     phase=LAL_TWOPI*(orbits - (REAL8)norbits);
00416     /*phase=LAL_TWOPI*(orbits);*/
00417 
00418     x = x + xdot*tt0;
00419 
00420     /* depending on whether we have eps derivs or w time derivs calculate e1 and e2 accordingly */
00421     if(params->nEll == 0){
00422       e1 = eps1 + eps1dot*tt0;
00423       e2 = eps2 + eps2dot*tt0;
00424     }
00425     else{
00426       ecc = sqrt(eps1*eps1 + eps2*eps2);
00427       ecc += edot*tt0;
00428       w_int = atan2(eps1, eps2);
00429       w_int = w_int + wdot*tt0; 
00430       e1 = ecc*sin(w_int);
00431       e2 = ecc*cos(w_int);
00432     }
00433 
00434     /* this timing delay (Roemer + Einstein) should be most important in most cases */ 
00435     DRE = x*(sin(phase)-0.5*(e1*cos(2.0*phase)-e2*sin(2.0*phase)));
00436     DREp = x*cos(phase);
00437     DREpp = -x*sin(phase);
00438 
00439     /* these params will normally be negligable */
00440     dlogbr = log(1.0-s*sin(phase));
00441     DS = -2.0*r*dlogbr;
00442     DA = a0*sin(phase) + b0*cos(phase);
00443 
00444     Dbb = DRE*(1.0-nb*DREp+(nb*DREp)*(nb*DREp) + 0.5*nb*nb*DRE*DREpp) + DS + DA;
00445 
00446     output->deltaT = -Dbb;
00447     /********************************************************/
00448   }
00449 
00450   /* for DD model - code partly adapted from TEMPO bnrydd.f */
00451   /* also used for MSS model (Wex 1998) - main sequence star orbit - this only has two lines
00452 different than DD model - TEMPO bnrymss.f */
00453   if(strstr(params->model, "DD") != NULL || strstr(params->model, "MSS") != NULL){
00454     REAL8 u, du=1.0;/* new eccentric anomaly */
00455     REAL8 Ae;       /* eccentricity parameter */
00456     REAL8 DRE;      /* Roemer delay + Einstein delay */
00457     REAL8       DREp, DREpp; /* see DD eqs 48 - 50 */
00458     REAL8 DS;       /* Shapiro delay */
00459     REAL8 DA;       /* aberation caused by pulsar rotation delay */
00460     REAL8 tt0;
00461     /* various variable use during calculation */
00462     REAL8 er, eth, an, k;
00463     REAL8 orbits, phase;
00464     INT4 norbits;
00465     REAL8 su, cu, onemecu, cae, sae;
00466     REAL8 sw, cw, alpha, beta, bg;
00467     REAL8 anhat, sqr1me2, cume, brace, dlogbr;
00468     REAL8 Dbb;    /* Delta barbar in DD eq 52 */
00469 
00470     REAL8 xi; /* parameter for MSS model - the only other one needed */
00471     
00472     /* fprintf(stderr, "You are using the Damour-Deruelle (DD) binary model.\n");*/
00473 
00474     /* part of code adapted from TEMPO bnrydd.f */
00475     an = LAL_TWOPI/Pb;
00476     k = wdot/an;
00477     xi = xdot/an; /* MSS parameter */
00478 
00479     tt0 = tb - T0;
00480     /* x = x + xdot*tt0; */
00481     e = e + edot*tt0;
00482     er = e*(1.0+dr);
00483     eth = e*(1.0+dth);
00484 
00485     orbits = (tt0/Pb) - 0.5*(pbdot+xpbdot)*(tt0/Pb)*(tt0/Pb);
00486     norbits = (INT4)floor(orbits);
00487 
00488     if(orbits < 0.0)
00489       norbits = norbits - 1;
00490 
00491     phase = LAL_TWOPI*(orbits - (REAL8)norbits);
00492 
00493     /* use numerical iteration to solve Kepler's eq for eccentric anomaly u */
00494     u = phase + e*sin(phase)*(1.0 + e*cos(phase));
00495     while(fabs(du) > 1.0e-12){
00496       du = (phase-(u-e*sin(u)))/(1.0-e*cos(u));
00497       u += du;
00498     }
00499 
00500     /* compute Ae as in TEMPO bnrydd.f */
00501     su = sin(u);
00502     cu = cos(u);
00503     onemecu = 1.0 - e*cu;
00504     cae = (cu - e)/onemecu;
00505     sae = sqrt(1.0 - e*e)*su/onemecu;
00506 
00507     Ae = atan2(sae,cae);
00508 
00509     if(Ae < 0.0)
00510       Ae = Ae + LAL_TWOPI;
00511 
00512     Ae = LAL_TWOPI*orbits + Ae - phase;
00513 
00514     w = w0 + k*Ae; /* add corrections to omega */ /* MSS also uses (om2dot, but not defined) */
00515     
00516     /* small difference between MSS and DD */
00517     if(strstr(params->model, "MSS") != NULL){
00518       x = x + xi*Ae; /* in bnrymss.f they also include a second time derivative of x (x2dot), but
00519 this isn't defined for either of the two pulsars currently using this model */
00520     }
00521     else
00522       x = x + xdot*tt0;
00523     
00524     /* now compute time delays as in DD eqs 46 - 52 */
00525 
00526     /* calculate Einstein and Roemer delay */
00527     sw = sin(w);
00528     cw = cos(w);
00529     alpha = x*sw;
00530     beta = x*sqrt(1.0-eth*eth)*cw;
00531     bg = beta + gamma;
00532     DRE = alpha*(cu-er)+bg*su;
00533     DREp = -alpha*su + bg*cu;
00534     DREpp = -alpha*cu - bg*su;
00535     anhat = an/onemecu;
00536 
00537     /* calculate Shapiro and abberation delays DD eqs 26, 27 */
00538     sqr1me2 = sqrt(1.0-e*e);
00539     cume = cu-e;
00540     brace = onemecu-s*(sw*cume + sqr1me2*cw*su);
00541     dlogbr = log(brace);
00542     DS = -2.0*r*dlogbr;
00543 
00544     /* this abberation delay is prob fairly small */
00545     DA = a0*(sin(w+Ae)+e*sw) + b0*(cos(w+Ae)+e*cw);
00546 
00547     /* timing difference */
00548     Dbb = DRE*(1.0 - anhat*DREp+anhat*anhat*DREp*DREp + 0.5*anhat*anhat*DRE*DREpp - 
00549           0.5*e*su*anhat*anhat*DRE*DREp/onemecu) + DS + DA;
00550 
00551     output->deltaT = -Dbb;
00552   }
00553 
00554   /* for DDGR model */  
00555 
00556   /* for Epstein-Haugan (EH) model - see Haugan, ApJ (1985) eqs 69 and 71 */
00557   
00558   /* check that the returned value is not a NaN */
00559   if( isnan(output->deltaT) ){
00560     XLAL_ERROR_VOID( fn, BINARYPULSARTIMINGH_ENAN );
00561   }
00562 }
00563 
00564 
00565 void
00566 LALReadTEMPOParFile(  LALStatus *status,
00567                       BinaryPulsarParams *output,
00568                       CHAR      *pulsarAndPath )
00569 {
00570   INITSTATUS(status, "LALReadTEMPOParFile", BINARYPULSARTIMINGC);
00571   ATTATCHSTATUSPTR(status);
00572   
00573   ASSERT(output != (BinaryPulsarParams *)NULL, status, 
00574   BINARYPULSARTIMINGH_ENULLOUTPUT, BINARYPULSARTIMINGH_MSGENULLOUTPUT);
00575 
00576   XLALReadTEMPOParFile( output, pulsarAndPath );
00577 
00578   DETATCHSTATUSPTR(status);
00579   RETURN(status);
00580 }
00581 
00582 void
00583 XLALReadTEMPOParFile( BinaryPulsarParams *output,
00584                       CHAR      *pulsarAndPath )
00585 {
00586   const CHAR *fn = "XLALReadTEMPOParFile()";
00587 
00588   FILE *fp=NULL;
00589   CHAR val[500][40]; /* string array to hold all the read in values 
00590                         500 strings of max 40 characters is enough */
00591   INT4 i=0, j=1, k;
00592 
00593   if( output == (BinaryPulsarParams *)NULL ){
00594     XLAL_ERROR_VOID( fn, XLAL_EFAULT );
00595   }
00596 
00597   output->model = NULL; /* set binary model to null - incase not a binary */
00598   
00599   /* set all output params to zero*/
00600   output->e=0.0;      /* orbital eccentricity */
00601   output->Pb=0.0;     /* orbital period (days) */
00602   output->w0=0.0;     /* logitude of periastron (deg) */
00603   output->x=0.0;      /* projected semi-major axis/speed of light (light secs) */
00604   output->T0=0.0;     /* time of orbital perisastron as measured in TDB (MJD) */
00605 
00606   output->e2=0.0;      
00607   output->Pb2=0.0;     
00608   output->w02=0.0;     
00609   output->x2=0.0;      
00610   output->T02=0.0;
00611 
00612   output->e3=0.0;      
00613   output->Pb3=0.0;     
00614   output->w03=0.0;     
00615   output->x3=0.0;      
00616   output->T03=0.0;
00617 
00618   output->xpbdot=0.0;  /* (10^-12) */
00619   
00620   output->eps1=0.0;       /* e*sin(w) */
00621   output->eps2=0.0;       /* e*cos(w) */
00622   output->eps1dot=0.0;
00623   output->eps2dot=0.0;
00624   output->Tasc=0.0;   /* time of the ascending node (used rather than T0) */
00625 
00626   for(i=0;i<12;i++){
00627     output->fb[i] = 0.;
00628     output->fbErr[i] = 0.;
00629   }
00630 
00631   output->nfb=0;
00632 
00633   output->wdot=0.0;   /* precesion of longitude of periastron w = w0 + wdot(tb-T0) (degs/year) */
00634   output->gamma=0.0;  /* gravitational redshift and time dilation parameter (s)*/
00635   output->Pbdot=0.0;  /* rate of change of Pb (dimensionless 10^-12) */
00636   output->xdot=0.0;   /* rate of change of x(=asini/c) - optional (10^-12)*/
00637   output->edot=0.0;   /* rate of change of e (10^-12)*/
00638 
00639   output->s=0.0;      /* Shapiro 'shape' parameter sin i */
00640 
00641   /*output.r=0.0; Shapiro 'range' parameter */
00642   output->dr=0.0;
00643   output->dth=0.0;    /* (10^-6) */
00644   output->a0=0.0;
00645   output->b0=0.0; /* abberation delay parameters */
00646 
00647   output->M=0.0;     /* M = m1 + m2 (m1 = pulsar mass, m2 = companion mass) */
00648   output->m2=0.0;    /* companion mass */
00649 
00650   output->f0=0.0;
00651   output->f1=0.0;
00652   output->f2=0.0;
00653   output->f3=0.0;
00654 
00655   output->ra=0.0;
00656   output->dec=0.0;
00657   output->pmra=0.0;
00658   output->pmdec=0.0;
00659 
00660   output->raErr=0.0;
00661   output->decErr=0.0;
00662   output->pmraErr=0.0;
00663   output->pmdecErr=0.0; 
00664 
00665   output->posepoch=0.0;
00666   output->pepoch=0.0;
00667   
00668   output->posepochErr=0.0;
00669   output->pepochErr=0.0;
00670   
00671   /* set all errors on params to zero */
00672   output->xpbdotErr=0.0;  /* (10^-12) */
00673   
00674   output->eps1Err=0.0;        /* e*sin(w) */
00675   output->eps2Err=0.0;        /* e*cos(w) */
00676   output->eps1dotErr=0.0;
00677   output->eps2dotErr=0.0;
00678   output->TascErr=0.0;    /* time of the ascending node (used rather than T0) */
00679 
00680   output->wdotErr=0.0;   /* precesion of longitude of periastron w = w0 + wdot(tb-T0) (degs/year) */
00681   output->gammaErr=0.0;  /* gravitational redshift and time dilation parameter (s)*/
00682   output->PbdotErr=0.0;  /* rate of change of Pb (dimensionless 10^-12) */
00683   output->xdotErr=0.0;   /* rate of change of x(=asini/c) - optional (10^-12)*/
00684   output->edotErr=0.0;   /* rate of change of e (10^-12)*/
00685   
00686   output->sErr=0.0;     /* Shapiro 'shape' parameter sin i */
00687   
00688   /*output->rErr=0.0;  Shapiro 'range' parameter */
00689   output->drErr=0.0;
00690   output->dthErr=0.0;   /* (10^-6) */
00691   output->a0Err=0.0;
00692   output->b0Err=0.0;    /* abberation delay parameters */
00693   
00694   output->MErr=0.0;     /* M = m1 + m2 (m1 = pulsar mass, m2 = companion mass) */
00695   output->m2Err=0.0;    /* companion mass */
00696   
00697   output->f0Err=0.0;
00698   output->f1Err=0.0;
00699   output->f2Err=0.0;
00700   output->f3Err=0.0;
00701 
00702   output->eErr =0.0;
00703   output->w0Err=0.0;
00704   output->PbErr=0.0;
00705   output->xErr=0.0;
00706   output->T0Err=0.0;
00707   
00708   output->e2Err =0.0;
00709   output->w02Err=0.0;
00710   output->Pb2Err=0.0;
00711   output->x2Err=0.0;
00712   output->T02Err=0.0;
00713   
00714   output->e3Err =0.0;
00715   output->w03Err=0.0;
00716   output->Pb3Err=0.0;
00717   output->x3Err=0.0;
00718   output->T03Err=0.0;
00719 
00720   if((fp = fopen(pulsarAndPath, "r")) == NULL){
00721     XLAL_ERROR_VOID( fn, XLAL_EIO );
00722   }
00723 
00724   /* read all the pulsar data into the string array */
00725   while(!feof(fp)){
00726     /* make sure val[i] is clear first */
00727     sprintf(val[i], "%s", "");
00728     
00729     fscanf(fp, "%s", val[i]);
00730     i++;
00731   }
00732   
00733   k=i; /* k is the end number */
00734   i=0; /* reset i */
00735   
00736   /* set pulsar values for output */
00737   /* in .par files first column will param name, second will be param value,
00738      if third is defined it will be an integer to tell TEMPO whether to fit
00739      the param or not (don't need this), fourth will be the error on the 
00740      param (in same units as the param) */
00741  
00742   /* convert all epochs given in MJD in .par files to secs in TDB  */
00743   while(1){
00744     j=i;
00745     if(!strcmp(val[i], "NAME") || !strcmp(val[i], "name")){
00746       output->name = XLALStringDuplicate(val[i+1]);
00747       j++;
00748     }
00749     else if(!strcmp(val[i],"ra") || !strcmp(val[i],"RA") || !strcmp(val[i],"RAJ")){
00750       /* this can be in form hh:mm:ss.ss or hhmmss.ss */
00751       output->ra = LALDegsToRads(val[i+1], "RA");
00752       j++;
00753 
00754       /* only try to get error if one exists */
00755       if(atoi(val[i+2])==1 && i+2<k){
00756         /* assuming at the moment that error is in arcsec */
00757         output->raErr = LAL_TWOPI*atof(val[i+3])/(24.0*60.0*60.0);
00758         j+=2;
00759       }
00760     }
00761     else if(!strcmp(val[i],"dec") || !strcmp(val[i],"DEC") || !strcmp(val[i],"DECJ")) {
00762       output->dec = LALDegsToRads(val[i+1], "DEC");
00763       j++;
00764 
00765       if(atoi(val[i+2])==1 && i+2<k){
00766         /* assuming at the moment that error is in arcsec */
00767         output->decErr = LAL_TWOPI*atof(val[i+3])/(360.0*60.0*60.0);
00768         j+=2;
00769       }
00770     }
00771     else if(!strcmp(val[i],"pmra") || !strcmp(val[i],"PMRA")) {
00772       /* convert pmra from mas/year to rads/sec */
00773       output->pmra = LAL_PI_180*atof(val[i+1])/(60.0*60.0*1000.*LAL_YRSID_SI);
00774       j++;
00775       if(atoi(val[i+2])==1 && i+2<k){
00776         output->pmraErr = LAL_PI_180*atof(val[i+3])/(60.0*60.0*1000.*LAL_YRSID_SI);
00777         j+=2;
00778       }
00779     }
00780     else if(!strcmp(val[i],"pmdec") || !strcmp(val[i],"PMDEC")) {
00781       /* convert pmdec from mas/year to rads/sec */
00782       output->pmdec = LAL_PI_180*atof(val[j+1])/(60.0*60.0*1000.*LAL_YRSID_SI);
00783       j++;
00784 
00785       if(atoi(val[i+2])==1 && i+2<k){
00786         output->pmdecErr = LAL_PI_180*atof(val[i+3])/(60.0*60.0*1000.*LAL_YRSID_SI);
00787         j+=2;
00788       }
00789     }
00790     else if(!strcmp(val[i],"pepoch") || !strcmp(val[i],"PEPOCH")) {
00791       output->pepoch = LALTDBMJDtoGPS(atof(val[i+1])); /* convert all epochs to from MJD to
00792         GPS seconds in TDB */
00793       j++;
00794 
00795     }
00796     else if( !strcmp(val[i],"posepoch") || !strcmp(val[i],"POSEPOCH")){
00797       output->posepoch = LALTDBMJDtoGPS(atof(val[i+1]));
00798       j++;
00799       /* position epoch in GPS seconds TDB */
00800     }
00801     else if( !strcmp(val[i],"f0") || !strcmp(val[i],"F0")) {
00802       /* in .par files exponents sometimes shown as D/d rather than e/E
00803          need way to check this as atof will not convert D (but will 
00804          work for e/E (if a d/D is present atof will convert the number 
00805          before the d/D but not the exponent */
00806       CHAR *loc;
00807 
00808       output->f0 = atof(val[i+1]);
00809       j++;
00810 
00811       if(atoi(val[i+2])==1 && i+2<k){
00812         /* check if exponent contains e/E or d/D or neither */
00813         if((loc = strstr(val[i+3], "D"))!=NULL || (loc = strstr(val[i+3], "d"))!=NULL){
00814           output->f0Err = atof(val[i+3])*pow(10, atof(loc+1));
00815         }
00816         else{
00817           output->f0Err = atof(val[i+3]);
00818         }
00819         j+=2;
00820       }
00821     }
00822     else if( !strcmp(val[i],"f1") || !strcmp(val[i],"F1")) {
00823       CHAR *loc;
00824 
00825       /* check if exponent contains e/E or d/D or neither */
00826       if((loc = strstr(val[i+1], "D"))!=NULL || (loc = strstr(val[i+1], "d"))!=NULL){
00827         output->f1 = atof(val[i+1])*pow(10, atof(loc+1));
00828       }
00829       else{
00830         output->f1 = atof(val[i+1]);
00831       }
00832       j++;
00833 
00834       if(atoi(val[i+2])==1 && i+2<k){
00835         /* check if exponent contains e/E or d/D or neither */
00836         if((loc = strstr(val[i+3], "D"))!=NULL || (loc = strstr(val[i+3], "d"))!=NULL){
00837           output->f1Err = atof(val[i+3])*pow(10, atof(loc+1));
00838         }
00839         else{
00840           output->f1Err = atof(val[i+3]);
00841         }
00842         j+=2;
00843       }
00844     }
00845     else if( !strcmp(val[i],"f2") || !strcmp(val[i],"F2")) {
00846       CHAR *loc;
00847   
00848       /* check if exponent contains e/E or d/D or neither */
00849       if((loc = strstr(val[i+1], "D"))!=NULL || (loc = strstr(val[i+1], "d"))!=NULL){
00850         output->f2 = atof(val[i+1])*pow(10, atof(loc+1));
00851       }
00852       else{
00853         output->f2 = atof(val[i+1]);
00854       }
00855       j++;
00856 
00857       if(atoi(val[i+2])==1 && i+2<k){
00858         /* check if exponent contains e/E or d/D or neither */
00859         if((loc = strstr(val[i+3], "D"))!=NULL || (loc = strstr(val[i+3], "d"))!=NULL){
00860           output->f2Err = atof(val[i+3])*pow(10, atof(loc+1));
00861         }
00862         else{
00863           output->f2Err = atof(val[i+3]);
00864         }
00865         j+=2;
00866       }
00867     }
00868     else if( !strcmp(val[i],"f3") || !strcmp(val[i],"F3")) {
00869       CHAR *loc;
00870 
00871       /* check if exponent contains e/E or d/D or neither */
00872       if((loc = strstr(val[i+1], "D"))!=NULL || (loc = strstr(val[i+1], "d"))!=NULL){
00873         output->f3 = atof(val[i+1])*pow(10, atof(loc+1));
00874       }
00875       else{
00876         output->f3 = atof(val[i+1]);
00877       }
00878       j++;
00879 
00880       if(atoi(val[i+2])==1 && i+2<k){
00881         /* check if exponent contains e/E or d/D or neither */
00882         if((loc = strstr(val[i+3], "D"))!=NULL || (loc = strstr(val[i+3], "d"))!=NULL){
00883           output->f3Err = atof(val[i+3])*pow(10, atof(loc+1));
00884         }
00885         else{
00886           output->f3Err = atof(val[i+3]);
00887         }
00888         j+=2;
00889       }
00890     }
00891     else if( !strcmp(val[i],"binary") || !strcmp(val[i],"BINARY")) {
00892       /*sprintf(output->model, "%s", val[j+1]);*/
00893       output->model = XLALStringDuplicate(val[i+1]);
00894       j++;
00895     }
00896     else if( !strcmp(val[i],"a1") || !strcmp(val[i],"A1")) {
00897       output->x = atof(val[i+1]);
00898       j++;
00899 
00900       if(atoi(val[i+2])==1 && i+2<k){
00901         output->xErr = atof(val[i+3]);
00902         j+=2;
00903       }
00904     }
00905     else if( !strcmp(val[i],"e") || !strcmp(val[i],"E") || !strcmp(val[i],"ECC") ||
00906       !strcmp(val[i],"ecc")) {
00907       output->e = atof(val[i+1]);
00908       j++;
00909 
00910       if(atoi(val[i+2])==1 && i+2<k){
00911         output->eErr = atof(val[i+3]);
00912         j+=2;
00913       }
00914     }
00915     else if( !strcmp(val[i],"pb") || !strcmp(val[i],"PB")) {
00916       output->Pb = atof(val[i+1]);
00917       j++;
00918 
00919       if(atoi(val[i+2])==1 && i+2<k){
00920         output->PbErr = atof(val[i+3]);
00921         j+=2;
00922       }
00923     }
00924     else if( !strcmp(val[i],"om") || !strcmp(val[i],"OM")) {
00925       output->w0 = atof(val[i+1]);
00926       j++;
00927 
00928       if(atoi(val[i+2])==1 && i+2<k){
00929         output->w0Err = atof(val[i+3]);
00930         j+=2;
00931       }
00932     }
00933     else if( !strcmp(val[i], "T0")){
00934       output->T0 = LALTDBMJDtoGPS(atof(val[i+1]));
00935       j++;
00936 
00937       if(atoi(val[i+2])==1 && i+2<k){
00938         output->T0Err = atof(val[i+3])*DAYSTOSECS; /* convert to seconds */
00939         j+=2;
00940       }
00941     }
00942     else if( !strcmp(val[i], "Tasc") || !strcmp(val[i], "TASC")){
00943       output->Tasc = LALTDBMJDtoGPS(atof(val[i+1]));
00944       j++;
00945 
00946       if(atoi(val[i+2])==1 && i+2<k){
00947         output->TascErr = atof(val[i+3])*DAYSTOSECS; /* convert to seconds; */
00948         j+=2;
00949       }
00950     }
00951     else if( !strcmp(val[i], "eps1") || !strcmp(val[i], "EPS1")){
00952       output->eps1 = atof(val[i+1]);
00953       j++;
00954 
00955       if(atoi(val[i+2])==1 && i+2<k){
00956         output->eps1Err = atof(val[i+3]);
00957         j+=2;
00958       }
00959     }
00960     else if( !strcmp(val[i], "eps2") || !strcmp(val[i], "EPS2")){
00961       output->eps2 = atof(val[i+1]);
00962       j++;
00963 
00964       if(atoi(val[i+2])==1 && i+2<k){
00965         output->eps2Err = atof(val[i+3]);
00966         j+=2;
00967       }
00968     }
00969     else if( !strcmp(val[i], "eps1dot") || !strcmp(val[i], "EPS1DOT")){
00970       output->eps1dot = atof(val[i+1]);
00971       j++;
00972 
00973       if(atoi(val[i+2])==1 && i+2<k){
00974         output->eps1dotErr = atof(val[i+3]);
00975         j+=2;
00976       }
00977     }
00978     else if( !strcmp(val[i], "eps2dot") || !strcmp(val[i], "EPS2DOT")){
00979       output->eps2dot = atof(val[i+1]);
00980       j++;
00981 
00982       if(atoi(val[i+2])==1 && i+2<k){
00983         output->eps2dotErr = atof(val[i+3]);
00984         j+=2;
00985       }
00986     }
00987     else if( !strcmp(val[i], "xpbdot") || !strcmp(val[i], "XPBDOT")){
00988       output->xpbdot = atof(val[i+1]);
00989       j++;
00990 
00991       if(atoi(val[i+2])==1 && i+2<k){
00992         output->xpbdotErr = atof(val[i+3]);
00993         j+=2;
00994       }
00995     }
00996     else if( !strcmp(val[i], "omdot") || !strcmp(val[i], "OMDOT")){
00997       output->wdot = atof(val[i+1]);
00998       j++;
00999 
01000       if(atoi(val[i+2])==1 && i+2<k){
01001         output->wdotErr = atof(val[i+3]);
01002         j+=2;
01003       }
01004     }
01005     else if( !strcmp(val[i], "pbdot") || !strcmp(val[i], "PBDOT")){
01006       output->Pbdot = atof(val[i+1]);
01007       j++;
01008 
01009       if(atoi(val[i+2])==1 && i+2<k){
01010         output->PbdotErr = atof(val[i+3]);
01011         j+=2;
01012       }
01013     }
01014     else if( !strcmp(val[i], "xdot") || !strcmp(val[i], "XDOT")){
01015       output->xdot = atof(val[i+1]);
01016       j++;
01017 
01018       if(atoi(val[i+2])==1 && i+2<k){
01019         output->xdotErr = atof(val[i+3]);
01020         j+=2;
01021       }
01022     }
01023     else if( !strcmp(val[i], "edot") || !strcmp(val[i], "EDOT")){
01024       output->edot = atof(val[i+1]);
01025       j++;
01026 
01027       if(atoi(val[i+2])==1 && i+2<k){
01028         output->edotErr = atof(val[i+3]);
01029         j+=2;
01030       }
01031     }
01032     else if( !strcmp(val[i], "gamma") || !strcmp(val[i], "GAMMA")){
01033       output->gamma = atof(val[i+1]);
01034       j++;
01035 
01036       if(atoi(val[i+2])==1 && i+2<k){
01037         output->gammaErr = atof(val[i+3]);
01038         j+=2;
01039       }
01040     }
01041     else if( !strcmp(val[i], "sini") || !strcmp(val[i], "SINI")){
01042       output->s = atof(val[i+1]);
01043       j++;
01044 
01045       if(atoi(val[i+2])==1 && i+2<k){
01046         output->sErr = atof(val[i+3]);
01047         j+=2;
01048       }
01049     }
01050     else if( !strcmp(val[i], "mtot") || !strcmp(val[i], "MTOT")){
01051       output->M = atof(val[i+1]);
01052       j++;
01053 
01054       if(atoi(val[i+2])==1 && i+2<k){
01055         output->MErr = atof(val[i+3]);
01056         j+=2;
01057       }
01058     }
01059     else if( !strcmp(val[i], "m2") || !strcmp(val[i], "M2")){
01060       output->m2 = atof(val[i+1]);
01061       j++;
01062 
01063       if(atoi(val[i+2])==1 && i+2<k){
01064         output->m2Err = atof(val[i+3]);
01065         j+=2;
01066       }
01067     }
01068     else if( !strcmp(val[i], "a0") || !strcmp(val[i], "A0")){
01069       output->a0 = atof(val[i+1]);
01070       j++;
01071 
01072       if(atoi(val[i+2])==1 && i+2<k){
01073         output->a0Err = atof(val[i+3]);
01074