BinaryPulsarTiming.c

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