LALPulsar  6.1.0.1-fe68b98
BinaryPulsarTiming.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2007 Jolien Creighton, Matt Pitkin
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with with program; see the file COPYING. If not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 */
19 
20 /**
21  * \author Matt Pitkin
22  * \date 2006
23  * \file
24  * \ingroup lalpulsar_general
25  * \brief Functions to calculate binary system time delays and read TEMPO pulsar parameter files
26  *
27  * Functions for calculating the timing delay to a signal from a pulsar in a
28  * binary system and reading pulsar parameters from TEMPO .par
29  * files.
30  * Models are taken from Taylor and Weisberg (1989) and use the
31  * naming conventions therein and used by TEMPO .
32  *
33  * ### Prototypes ###
34  *
35  *
36  * ### Description ###
37  *
38  * The main function computes the time delay of a signal from a pulsar in a
39  * binary system due to doppler shifts and relativistic delays,
40  * \f{equation}{
41  * \Delta{}t = t_\textrm{Roemer} + t_\textrm{Shapiro} + t_\textrm{Einstein} + t_\textrm{
42  * Abberation},
43  * \f}
44  * where \f$ t_\textrm{Roemer} \f$ is the light travel time, \f$ t_\textrm{Shapiro} \f$ is the
45  * General relativistic time delay, \f$ t_\textrm{Einstein} \f$ is the special
46  * relativistic time delay, and \f$ t_\textrm{Abberation} \f$ is the delay caused by the
47  * pulsars' rotation. There are several models of the binary systems, described
48  * in \cite TaylorWeisberg1989 , of which the four most common are so far
49  * implemented. The four models are the Blandford-Teukolsky model (BT)
50  * \cite BlandfordTeukolsky1976 , the low ellipticity model (ELL1)
51  * \cite ChLangeetal2001 , Damour-Deruelle model (DD) \cite DamourDeruelle1985 ,
52  * and the main sequence system model (MSS) \cite Wex1998 .
53  * These four models all use the five main binary parameters: the longitude of
54  * periastron \f$ \omega_0 \f$ , the eccentricity of the orbit \f$ e \f$ , the orbital period
55  * \f$ P \f$ , the time of periastron/or the time of ascension of the first node
56  * \f$ T_0 \f$ / \f$ T_{\textrm{asc}} \f$ , and the projected semi-major axis \f$ a\sin{}i \f$ . The are
57  * also many other model dependent parameters. These routines closely follow
58  * those used in the radio astronomy package TEMPO. A further model from TEMPO2
59  * called T2 is also implemented in a basic form. The model is generally based
60  * on the DD model, but will convert to ELL1 if the \c eps parameters are set.
61  * At the moment this (T2) does not include multiple companions in the orbit,
62  * but does encompass the DDS model. It also can include Kopeikin terms that
63  * take account of the effect of the binary orbit on the parallax.
64  *
65  * Radio astronomers fit pulsar parameters using TEMPO which will output
66  * the parameters in a <tt>.par</tt> file. The values allowed in this file can be
67  * found in the TEMPO documentation. A function is included to extract these
68  * parameters from the <tt>.par</tt> files and put them into a
69  * \c BinaryPulsarParams structure, it will set any unused parameters to
70  * zero or \c NULL. All parameters are in the units used by TEMPO with any
71  * conversion to SI units occuring within the binary timing routines. A function
72  * is also included which converts a string containing the right ascension or
73  * declination in the format <tt>ddd/hh:mm:ss.s</tt> or <tt>ddd/hhmmss.s</tt>
74  * (as is given in the <tt>.par</tt> file) into a \c REAL8 value in
75  * radians.
76  *
77  * ### Notes ###
78  *
79  */
80 
81 /* Matt Pitkin 29/04/04 */
82 
83 #include <lal/BinaryPulsarTiming.h>
84 
85 #include <string.h>
86 #include <math.h>
87 #include <lal/LALConstants.h>
88 #include <lal/LALStdlib.h>
89 #include <lal/LALString.h>
90 #include <lal/SSBtimes.h>
91 
92 #ifdef __GNUC__
93 #define UNUSED __attribute__ ((unused))
94 #else
95 #define UNUSED
96 #endif
97 
98 #define AULTSC 499.00478364 /* number of light seconds in AU (from tempo2.h) */
99 
100 /**
101  * XLAL function to compute the eccentric anomaly iteratively from Kelper's
102  * equation.
103  */
105 {
106  REAL8 du;
107 
108  *u = phase + ecc * sin( phase ) / sqrt( 1.0 - 2.*ecc * cos( phase ) + ecc * ecc );
109  do {
110  du = ( phase - ( *u - ecc * sin( *u ) ) ) / ( 1.0 - ecc * cos( *u ) );
111  ( *u ) += du;
112  } while ( fabs( du ) > 1.e-14 );
113 }
114 
115 
116 /**
117  * XLAL function to compute Kopeikin terms that include the effect of
118  * binary orbital parameters of parallax
119  */
122  BinaryPulsarInput *in )
123 {
124  REAL8 sini, cosi, tani;
125  REAL8 sin_delta, cos_delta, sin_alpha, cos_alpha;
126  REAL8 delta_i0, delta_j0;
127  REAL8 sin_omega, cos_omega;
128  REAL8 ca, sa, cd, sd;
129  REAL8 delt;
130  REAL8 posPulsar[3], velPulsar[3], psrPos[3];
131  REAL8 tt0;
132  REAL8 dpara; /* parallax */
133  REAL8 x;
134 
135  sini = sin( params->kin );
136  cosi = cos( params->kin );
137  tani = sini / cosi;
138 
139  sin_omega = sin( params->kom );
140  cos_omega = cos( params->kom );
141 
142  /* ki_dot is set in tempo2 function, but not used */
143  /* ki_dot = -params.pmra * sin_omega + params.pmdec*cos_omega; */
144  /* Equation 8 in Kopeikin 1996 */
145  // (*x) += ((*x)*ki_dot/tani)*tt0;
146  /* Equation 9 in Kopeikin 1996 */
147  //(*omz) += (pmra*cos_omega+pmdec*sin_omega)/sini*tt0;
148 
149  /* Now modify x and omega due to the annual-orbital parallax term
150  * as described in Kopeikin 1995
151  *
152  * Require knowledge of the barycentric earth position vector - earth_ssb
153  */
154 
155  /* get pulsar vector */
156  ca = cos( params->ra );
157  sa = sin( params->ra );
158  cd = cos( params->dec );
159  sd = sin( params->dec );
160 
161  posPulsar[0] = ca * cd;
162  posPulsar[1] = sa * cd;
163  posPulsar[2] = sd;
164 
165  velPulsar[0] = -params->pmra / cos( params->dec ) * sa * cd - params->pmdec * ca * sd;
166  velPulsar[1] = params->pmra / cos( params->dec ) * ca * cd - params->pmdec * sa * sd;
167  velPulsar[2] = params->pmdec * cd;
168 
169  delt = in->tb - params->posepoch;
170  /* add proper motion onto the pulsar position */
171  for ( UINT4 i = 0; i < 3; i++ ) {
172  psrPos[i] = posPulsar[i] + delt * velPulsar[i];
173  }
174 
175  /* Obtain vector pointing at the pulsar */
176  sin_delta = psrPos[2];
177  cos_delta = cos( asin( sin_delta ) );
178  sin_alpha = psrPos[1] / cos_delta;
179  cos_alpha = psrPos[0] / cos_delta;
180 
181  /* Equation 15 in Kopeikin 1995 */
182  delta_i0 = -in->earth.posNow[0] / AULTSC * sin_alpha +
183  in->earth.posNow[1] / AULTSC * cos_alpha;
184  /* Equation 16 in Kopeikin 1995 */
185  delta_j0 = -in->earth.posNow[0] / AULTSC * sin_delta * cos_alpha -
186  in->earth.posNow[1] / AULTSC * sin_delta * sin_alpha +
187  in->earth.posNow[2] / AULTSC * cos_delta;
188 
189  dpara = params->px;
190  x = params->x;
191 
192  /* xpr and ypr are set in tempo2 function, but not used */
193  /* xpr = delta_i0*sin_omega - delta_j0*cos_omega;
194  ypr = delta_i0*cos_omega + delta_j0*sin_omega; */
195 
196  /* Equations 18 and 19 in Kopeikin 1995 */
197  if ( params->daopset ) {
198  REAL8 daop = params->daop;
199 
200  kop->DK011 = - x / daop / sini * delta_i0 * sin_omega;
201  kop->DK012 = - x / daop / sini * delta_j0 * cos_omega;
202  kop->DK013 = - x / daop / sini * delta_i0 * cos_omega;
203  kop->DK014 = x / daop / sini * delta_j0 * sin_omega;
204 
205  kop->DK021 = x / daop / tani * delta_i0 * cos_omega;
206  kop->DK022 = -x / daop / tani * delta_j0 * sin_omega;
207  kop->DK023 = x / daop / tani * delta_i0 * sin_omega;
208  kop->DK024 = x / daop / tani * delta_j0 * cos_omega;
209  } else {
210  kop->DK011 = -x * dpara / sini * delta_i0 * sin_omega;
211  kop->DK012 = -x * dpara / sini * delta_j0 * cos_omega;
212  kop->DK013 = -x * dpara / sini * delta_i0 * cos_omega;
213  kop->DK014 = x * dpara / sini * delta_j0 * sin_omega;
214 
215  kop->DK021 = x * dpara / tani * delta_i0 * cos_omega;
216  kop->DK022 = -x * dpara / tani * delta_j0 * sin_omega;
217  kop->DK023 = x * dpara / tani * delta_i0 * sin_omega;
218  kop->DK024 = x * dpara / tani * delta_j0 * cos_omega;
219  }
220 
221  if ( params->T0 != 0. ) {
222  tt0 = in->tb - params->T0;
223  } else if ( params->Tasc != 0. ) {
224  tt0 = in->tb - params->Tasc;
225  } else {
226  XLALPrintError( "%s: Neither T0 or Tasc is defined!\n", __func__ );
228  }
229 
230  kop->DK031 = x * tt0 / sini * params->pmra * sin_omega;
231  kop->DK032 = x * tt0 / sini * params->pmdec * cos_omega;
232  kop->DK033 = x * tt0 / sini * params->pmra * cos_omega;
233  kop->DK034 = -x * tt0 / sini * params->pmdec * sin_omega;
234 
235  kop->DK041 = x * tt0 / tani * params->pmra * cos_omega;
236  kop->DK042 = -x * tt0 / tani * params->pmdec * sin_omega;
237  kop->DK043 = -x * tt0 / tani * params->pmra * sin_omega;
238  kop->DK044 = -x * tt0 / tani * params->pmdec * cos_omega;
239 }
240 
241 
244  BinaryPulsarInput *in )
245 {
246  REAL8 sini, cosi, tani;
247  REAL8 sin_delta, cos_delta, sin_alpha, cos_alpha;
248  REAL8 delta_i0, delta_j0;
249  REAL8 sin_omega, cos_omega;
250  REAL8 ca, sa, cd, sd;
251  REAL8 delt;
252  REAL8 posPulsar[3], velPulsar[3], psrPos[3];
253  REAL8 tt0;
254  REAL8 dpara; /* parallax */
255  REAL8 x;
256 
257  REAL8 kin = PulsarGetREAL8ParamOrZero( params, "KIN" );
258  sini = sin( kin );
259  cosi = cos( kin );
260  tani = sini / cosi;
261 
262  REAL8 kom = PulsarGetREAL8ParamOrZero( params, "KOM" );
263  sin_omega = sin( kom );
264  cos_omega = cos( kom );
265 
266  /* ki_dot is set in tempo2 function, but not used */
267  /* ki_dot = -params.pmra * sin_omega + params.pmdec*cos_omega; */
268  /* Equation 8 in Kopeikin 1996 */
269  // (*x) += ((*x)*ki_dot/tani)*tt0;
270  /* Equation 9 in Kopeikin 1996 */
271  //(*omz) += (pmra*cos_omega+pmdec*sin_omega)/sini*tt0;
272 
273  /* Now modify x and omega due to the annual-orbital parallax term
274  * as described in Kopeikin 1995
275  *
276  * Require knowledge of the barycentric earth position vector - earth_ssb
277  */
278 
279  REAL8 dec = 0.;
280  REAL8 ra = 0.;
281  if ( PulsarCheckParam( params, "RAJ" ) ) {
282  ra = PulsarGetREAL8Param( params, "RAJ" );
283  } else if ( PulsarCheckParam( params, "RA" ) ) {
284  ra = PulsarGetREAL8Param( params, "RA" );
285  }
286 
287  if ( PulsarCheckParam( params, "DECJ" ) ) {
288  dec = PulsarGetREAL8Param( params, "DECJ" );
289  } else if ( PulsarCheckParam( params, "DEC" ) ) {
290  dec = PulsarGetREAL8Param( params, "DEC" );
291  }
292 
293  /* get pulsar vector */
294  ca = cos( ra );
295  sa = sin( ra );
296  cd = cos( dec );
297  sd = sin( dec );
298 
299  posPulsar[0] = ca * cd;
300  posPulsar[1] = sa * cd;
301  posPulsar[2] = sd;
302 
303  REAL8 pmra = PulsarGetREAL8ParamOrZero( params, "PMRA" );
304  REAL8 pmdec = PulsarGetREAL8ParamOrZero( params, "PMDEC" );
305  velPulsar[0] = -pmra / cos( dec ) * sa * cd - pmdec * ca * sd;
306  velPulsar[1] = pmra / cos( dec ) * ca * cd - pmdec * sa * sd;
307  velPulsar[2] = pmdec * cd;
308 
309  delt = in->tb - PulsarGetREAL8ParamOrZero( params, "POSEPOCH" );
310  /* add proper motion onto the pulsar position */
311  for ( UINT4 i = 0; i < 3; i++ ) {
312  psrPos[i] = posPulsar[i] + delt * velPulsar[i];
313  }
314 
315  /* Obtain vector pointing at the pulsar */
316  sin_delta = psrPos[2];
317  cos_delta = cos( asin( sin_delta ) );
318  sin_alpha = psrPos[1] / cos_delta;
319  cos_alpha = psrPos[0] / cos_delta;
320 
321  /* Equation 15 in Kopeikin 1995 */
322  delta_i0 = -in->earth.posNow[0] / AULTSC * sin_alpha +
323  in->earth.posNow[1] / AULTSC * cos_alpha;
324  /* Equation 16 in Kopeikin 1995 */
325  delta_j0 = -in->earth.posNow[0] / AULTSC * sin_delta * cos_alpha -
326  in->earth.posNow[1] / AULTSC * sin_delta * sin_alpha +
327  in->earth.posNow[2] / AULTSC * cos_delta;
328 
329  dpara = PulsarGetREAL8ParamOrZero( params, "PX" );
331 
332  /* xpr and ypr are set in tempo2 function, but not used */
333  /* xpr = delta_i0*sin_omega - delta_j0*cos_omega;
334  ypr = delta_i0*cos_omega + delta_j0*sin_omega; */
335 
336  /* Equations 18 and 19 in Kopeikin 1995 */
337  if ( PulsarCheckParam( params, "D_AOP" ) ) {
338  REAL8 daop = PulsarGetREAL8Param( params, "D_AOP" );
339 
340  kop->DK011 = - x / daop / sini * delta_i0 * sin_omega;
341  kop->DK012 = - x / daop / sini * delta_j0 * cos_omega;
342  kop->DK013 = - x / daop / sini * delta_i0 * cos_omega;
343  kop->DK014 = x / daop / sini * delta_j0 * sin_omega;
344 
345  kop->DK021 = x / daop / tani * delta_i0 * cos_omega;
346  kop->DK022 = -x / daop / tani * delta_j0 * sin_omega;
347  kop->DK023 = x / daop / tani * delta_i0 * sin_omega;
348  kop->DK024 = x / daop / tani * delta_j0 * cos_omega;
349  } else {
350  kop->DK011 = -x * dpara / sini * delta_i0 * sin_omega;
351  kop->DK012 = -x * dpara / sini * delta_j0 * cos_omega;
352  kop->DK013 = -x * dpara / sini * delta_i0 * cos_omega;
353  kop->DK014 = x * dpara / sini * delta_j0 * sin_omega;
354 
355  kop->DK021 = x * dpara / tani * delta_i0 * cos_omega;
356  kop->DK022 = -x * dpara / tani * delta_j0 * sin_omega;
357  kop->DK023 = x * dpara / tani * delta_i0 * sin_omega;
358  kop->DK024 = x * dpara / tani * delta_j0 * cos_omega;
359  }
360 
362  REAL8 Tasc = PulsarGetREAL8ParamOrZero( params, "TASC" );
363  if ( T0 != 0. ) {
364  tt0 = in->tb - T0;
365  } else if ( Tasc != 0. ) {
366  tt0 = in->tb - Tasc;
367  } else {
368  XLALPrintError( "%s: Neither T0 or Tasc is defined!\n", __func__ );
370  }
371 
372  kop->DK031 = x * tt0 / sini * pmra * sin_omega;
373  kop->DK032 = x * tt0 / sini * pmdec * cos_omega;
374  kop->DK033 = x * tt0 / sini * pmra * cos_omega;
375  kop->DK034 = -x * tt0 / sini * pmdec * sin_omega;
376 
377  kop->DK041 = x * tt0 / tani * pmra * cos_omega;
378  kop->DK042 = -x * tt0 / tani * pmdec * sin_omega;
379  kop->DK043 = -x * tt0 / tani * pmra * sin_omega;
380  kop->DK044 = -x * tt0 / tani * pmdec * cos_omega;
381 }
382 
383 
384 
385 /**
386  * Calculate the binary system time delay using the pulsar parameters in
387  * \c params
388  */
389 void
392  BinaryPulsarInput *input,
394 {
395  INITSTATUS( status );
397 
398  /* Check input arguments */
399  ASSERT( input != ( BinaryPulsarInput * )NULL, status,
401 
402  ASSERT( output != ( BinaryPulsarOutput * )NULL, status,
404 
405  ASSERT( params != ( BinaryPulsarParams * )NULL, status,
407 
408  ASSERT( ( !strcmp( params->model, "BT" ) ) ||
409  ( !strcmp( params->model, "BT1P" ) ) ||
410  ( !strcmp( params->model, "BT2P" ) ) ||
411  ( !strcmp( params->model, "BTX" ) ) ||
412  ( !strcmp( params->model, "ELL1" ) ) ||
413  ( !strcmp( params->model, "DD" ) ) ||
414  ( !strcmp( params->model, "DDS" ) ) ||
415  ( !strcmp( params->model, "MSS" ) ) ||
416  ( !strcmp( params->model, "T2" ) ), status,
419 
421 
423  RETURN( status );
424 }
425 
426 
427 /**
428  * XLAL function to compute the binary time delay
429  */
430 void
432  BinaryPulsarInput *input,
434 {
435  REAL8 dt = 0.; /* binary pulsar deltaT */
436  REAL8 x, xdot; /* x = asini/c */
437  REAL8 w = 0; /* longitude of periastron */
438  REAL8 e, edot; /* eccentricity */
439  REAL8 eps1, eps2;
440  REAL8 eps1dot, eps2dot;
441  REAL8 w0, wdot;
442  REAL8 Pb, pbdot;
443  REAL8 xpbdot;
444  REAL8 T0, Tasc, tb = 0.; /* time parameters */
445 
446  REAL8 s, r; /* Shapiro shape and range params */
447  REAL8 lal_gamma; /* time dilation and grav redshift */
448  REAL8 dr, dth;
449  REAL8 shapmax; /* Shapiro max parameter for DDS model */
450  REAL8 a0, b0; /* abberation parameters */
451 
452  REAL8 m2;
453  const REAL8 c3 = ( REAL8 )LAL_C_SI * ( REAL8 )LAL_C_SI * ( REAL8 )LAL_C_SI;
454 
455  CHAR *model = params->model;
456 
457  /* Check input arguments */
458  if ( input == ( BinaryPulsarInput * )NULL ) {
460  }
461 
462  if ( output == ( BinaryPulsarOutput * )NULL ) {
464  }
465 
466  if ( params == ( BinaryPulsarParams * )NULL ) {
468  }
469 
470  if ( ( !strcmp( params->model, "BT" ) ) &&
471  ( !strcmp( params->model, "BT1P" ) ) &&
472  ( !strcmp( params->model, "BT2P" ) ) &&
473  ( !strcmp( params->model, "BTX" ) ) &&
474  ( !strcmp( params->model, "ELL1" ) ) &&
475  ( !strcmp( params->model, "DD" ) ) &&
476  ( !strcmp( params->model, "DDS" ) ) &&
477  ( !strcmp( params->model, "MSS" ) ) &&
478  ( !strcmp( params->model, "T2" ) ) ) {
480  }
481 
482  /* convert certain params to SI units */
483  w0 = params->w0;
484  wdot = params->wdot; /* wdot in rads/s */
485 
486  Pb = params->Pb; /* period in secs */
487  pbdot = params->Pbdot;
488 
489  T0 = params->T0; /* these should be in TDB in seconds */
490  Tasc = params->Tasc;
491 
492  e = params->e;
493  edot = params->edot;
494  eps1 = params->eps1;
495  eps2 = params->eps2;
496  eps1dot = params->eps1dot;
497  eps2dot = params->eps2dot;
498 
499  x = params->x;
500  xdot = params->xdot;
501  xpbdot = params->xpbdot;
502 
503  lal_gamma = params->gamma;
504  s = params->s; /* sin i */
505  dr = params->dr;
506  dth = params->dth;
507  shapmax = params->shapmax;
508 
509  a0 = params->a0;
510  b0 = params->b0;
511 
512  m2 = params->m2;
513 
514  /* Shapiro range parameter r defined as Gm2/c^3 (secs) */
515  r = LAL_G_SI * m2 / c3;
516 
517  /* if T0 is not defined, but Tasc is */
518  if ( T0 == 0.0 && Tasc != 0.0 && eps1 == 0.0 && eps2 == 0.0 ) {
519  REAL8 fe, uasc, Dt; /* see TEMPO tasc2t0.f */
520 
521  fe = sqrt( ( 1.0 - e ) / ( 1.0 + e ) );
522  uasc = 2.0 * atan( fe * tan( w0 / 2.0 ) );
523  Dt = ( Pb / LAL_TWOPI ) * ( uasc - e * sin( uasc ) );
524 
525  T0 = Tasc + Dt;
526  }
527 
528  /* set time at which to calculate the binary time delay */
529  tb = input->tb;
530 
531  /* for BT, BT1P and BT2P models (and BTX model, but only for one orbit) */
532  if ( strstr( model, "BT" ) != NULL ) {
533  REAL8 tt0;
534  REAL8 orbits = 0.;
535  INT4 norbits = 0.;
536  REAL8 phase; /* same as mean anomaly */
537  REAL8 u = 0.0; /* eccentric anomaly */
538 
539  INT4 nplanets = 1; /* number of orbiting bodies in system */
540  INT4 i = 1, j = 1;
541  REAL8 fac = 1.; /* factor in front of fb coefficients */
542 
543  REAL8 su = 0., cu = 0.;
544  REAL8 sw = 0., cw = 0.;
545 
546  /* work out number of orbits i.e. have we got a BT1P or BT2P model */
547  if ( !strcmp( model, "BT1P" ) ) {
548  nplanets = 2;
549  }
550  if ( !strcmp( model, "BT2P" ) ) {
551  nplanets = 3;
552  }
553 
554  for ( i = 1 ; i < nplanets + 1 ; i++ ) {
555 
556  /* set some vars for bnrybt.f (TEMPO) method */
557  /*REAL8 tt;
558  REAL8 som;
559  REAL8 com;
560  REAL8 alpha, beta;*/
561  /*REAL8 q, r, s;*/
562 
563  /*fprintf(stderr, "You are using the Blandford-Teukolsky (BT) binary
564  model.\n");*/
565 
566  if ( i == 2 ) {
567  T0 = params->T02;
568  w0 = params->w02;
569  x = params->x2;
570  e = params->e2;
571  Pb = params->Pb2;
572  } else if ( i == 3 ) {
573  T0 = params->T03;
574  w0 = params->w03;
575  x = params->x3;
576  e = params->e3;
577  Pb = params->Pb3;
578  }
579 
580  tt0 = tb - T0;
581 
582  /* only do relativistic corrections for first orbit */
583  if ( i == 1 ) {
584  x = x + xdot * tt0;
585  e = e + edot * tt0;
586  w = w0 + wdot * tt0; /* calculate w */
587 
588  if ( !strcmp( model, "BTX" ) ) {
589  fac = 1.;
590  for ( j = 1 ; j < params->nfb + 1; j++ ) {
591  fac /= ( REAL8 )j;
592  orbits += fac * params->fb[j - 1] * pow( tt0, j );
593  }
594  } else {
595  orbits = tt0 / Pb - 0.5 * ( pbdot + xpbdot ) * ( tt0 / Pb ) * ( tt0 / Pb );
596  }
597  } else {
598  orbits = tt0 / Pb;
599  }
600 
601  norbits = ( INT4 )orbits;
602 
603  if ( orbits < 0. ) {
604  norbits--;
605  }
606 
607  phase = LAL_TWOPI * ( orbits - ( REAL8 )norbits ); /* called phase in TEMPO */
608 
609  /* compute eccentric anomaly */
610  XLALComputeEccentricAnomaly( phase, e, &u );
611 
612  su = sin( u );
613  cu = cos( u );
614 
615  /*fprintf(stderr, "Eccentric anomaly = %f, phase = %f.\n", u, phase);*/
616  sw = sin( w );
617  cw = cos( w );
618 
619  /* see eq 5 of Taylor and Weisberg (1989) */
620  /**********************************************************/
621  if ( !strcmp( model, "BTX" ) ) {
622  /* dt += (x*sin(w)*(cos(u)-e) + (x*cos(w)*sqrt(1.0-e*e) +
623  lal_gamma)*sin(u))*(1.0 - params->fb[0]*(x*cos(w)*sqrt(1.0 -
624  e*e)*cos(u) - x*sin(w)*sin(u))/(1.0 - e*cos(u))); */
625  dt += ( x * sw * ( cu - e ) + ( x * cw * sqrt( 1.0 - e * e ) +
626  lal_gamma ) * su ) * ( 1.0 - LAL_TWOPI * params->fb[0] * ( x * cw * sqrt( 1.0 -
627  e * e ) * cu - x * sw * su ) / ( 1.0 - e * cu ) );
628  } else {
629  /* dt += (x*sin(w)*(cos(u)-e) + (x*cos(w)*sqrt(1.0-e*e) +
630  lal_gamma)*sin(u))*(1.0 - (LAL_TWOPI/Pb)*(x*cos(w)*sqrt(1.0 -
631  e*e)*cos(u) - x*sin(w)*sin(u))/(1.0 - e*cos(u))); */
632  dt += ( x * sw * ( cu - e ) + ( x * cw * sqrt( 1.0 - e * e ) +
633  lal_gamma ) * su ) * ( 1.0 - ( LAL_TWOPI / Pb ) * ( x * cw * sqrt( 1.0 -
634  e * e ) * cu - x * sw * su ) / ( 1.0 - e * cu ) );
635  }
636  /**********************************************************/
637  }
638 
639  /* use method from Taylor etal 1976 ApJ Lett and used in bnrybt.f */
640  /**********************************************************/
641  /*tt = 1.0-e*e;
642  som = sin(w);
643  com = cos(w);
644  alpha = x*som;
645  beta = x*com*sqrt(tt);
646  q = alpha*(cos(u)-e) + (beta+lal_gamma)*sin(u);
647  r = -alpha*sin(u) + beta*cos(u);
648  s = 1.0/(1.0-e*cos(u));
649  dt = -(-q+(LAL_TWOPI/Pb)*q*r*s);*/
650  /**********************************************************/
651  /* There appears to be NO difference between either method */
652 
653  output->deltaT = -dt;
654  }
655 
656  /* for ELL1 model (low eccentricity orbits so use eps1 and eps2) */
657  /* see Appendix A, Ch. Lange etal, MNRAS (2001) (also accept T2 model if
658  eps values are set - this will include Kopeikin terms if necessary) */
659  if ( !strcmp( model, "ELL1" ) || ( !strcmp( model, "T2" ) && eps1 != 0. ) ) {
660  REAL8 nb;
661  REAL8 tt0;
662  REAL8 w_int; /* omega internal to this model */
663  REAL8 orbits, phase;
664  INT4 norbits;
665  REAL8 e1, e2, ecc;
666  REAL8 DRE, DREp, DREpp; /* Roemer and Einstein delays (cf DD) */
667  REAL8 dlogbr;
668  REAL8 DS, DA; /* Shapiro delay and Abberation delay terms */
669  REAL8 Dbb;
670  REAL8 DAOP, DSR; /* Kopeikin delay terms */
671  REAL8 fac = 1.; /* factor in front of fb coefficients */
672 
673  KopeikinTerms kt;
674  REAL8 Ck, Sk;
675 
676  REAL8 sp = 0., cp = 0., s2p = 0., c2p = 0.;
677 
678  /* fprintf(stderr, "You are using the ELL1 low eccentricity orbit model.\n");*/
679 
680  /*********************************************************/
681  /* CORRECT CODE (as in TEMPO bnryell1.f) FROM HERE */
682 
683  ecc = sqrt( eps1 * eps1 + eps2 * eps2 );
684 
685  /* if Tasc is not defined convert T0 */
686  if ( Tasc == 0.0 && T0 != 0.0 ) {
687  REAL8 fe, uasc, Dt; /* see TEMPO tasc2t0.f */
688 
689  fe = sqrt( ( 1.0 - ecc ) / ( 1.0 + ecc ) );
690  uasc = 2.0 * atan( fe * tan( w0 / 2.0 ) );
691  Dt = ( Pb / LAL_TWOPI ) * ( uasc - ecc * sin( uasc ) );
692 
693  /* rearrange from what's in tasc2t0.f */
694  Tasc = T0 - Dt;
695  }
696 
697  tt0 = tb - Tasc;
698 
699  /* handle higher orbital frequency derivatives if present */
700  if ( params->nfb > 0 ) {
701  /* set period from first orbital frequency value */
702  Pb = 1. / params->fb[0];
703  orbits = tt0 / Pb;
704 
705  fac = 1.;
706  for ( UINT4 j = 1 ; j < ( UINT4 )params->nfb; j++ ) {
707  fac /= ( REAL8 )( j + 1 );
708  orbits += fac * params->fb[j] * pow( tt0, j + 1 );
709  }
710  } else {
711  orbits = tt0 / Pb - 0.5 * ( pbdot + xpbdot ) * ( tt0 / Pb ) * ( tt0 / Pb );
712  }
713 
714  nb = LAL_TWOPI / Pb;
715 
716  norbits = ( INT4 )orbits;
717  if ( orbits < 0.0 ) {
718  norbits--;
719  }
720 
721  phase = LAL_TWOPI * ( orbits - ( REAL8 )norbits );
722 
723  x = x + xdot * tt0;
724 
725  /* depending on whether we have eps derivs or w time derivs calculate e1 and e2 accordingly */
726  if ( params->nEll == 0 ) {
727  e1 = eps1 + eps1dot * tt0;
728  e2 = eps2 + eps2dot * tt0;
729  } else {
730  ecc = sqrt( eps1 * eps1 + eps2 * eps2 );
731  ecc += edot * tt0;
732  w_int = atan2( eps1, eps2 );
733  w_int = w_int + wdot * tt0;
734 
735  e1 = ecc * sin( w_int );
736  e2 = ecc * cos( w_int );
737  }
738 
739  //sin_cos_LUT(&sp, &cp, phase);
740  //sin_cos_LUT(&s2p, &c2p, 2.*phase);
741  sp = sin( phase );
742  cp = cos( phase );
743  s2p = sin( 2.*phase );
744  c2p = cos( 2.*phase );
745 
746  /* this timing delay (Roemer + Einstein) should be most important in most cases */
747  /* DRE = x*(sin(phase)-0.5*(e1*cos(2.0*phase)-e2*sin(2.0*phase)));
748  DREp = x*cos(phase);
749  DREpp = -x*sin(phase); */
750  DRE = x * ( sp - 0.5 * ( e1 * c2p - e2 * s2p ) );
751  DREp = x * cp;
752  DREpp = -x * sp;
753 
754  /* these params will normally be negligable */
755  dlogbr = log( 1.0 - s * sp );
756  DS = -2.0 * r * dlogbr;
757  DA = a0 * sp + b0 * cp;
758 
759  /* compute Kopeikin terms */
760  if ( params->kinset && params->komset && ( params->pmra != 0. ||
761  params->pmdec != 0. ) ) {
762  XLALComputeKopeikinTerms( &kt, params, input );
763 
764  Ck = sp - 0.5 * ( e1 * c2p - e2 * s2p );
765  Sk = cp + 0.5 * ( e2 * c2p + e1 * s2p );
766 
767  DAOP = ( kt.DK011 + kt.DK012 ) * Ck - ( kt.DK021 + kt.DK022 ) * Sk;
768  DSR = ( kt.DK031 + kt.DK032 ) * Ck + ( kt.DK041 + kt.DK042 ) * Sk;
769  } else {
770  DAOP = 0.;
771  DSR = 0.;
772  }
773 
774  Dbb = DRE * ( 1.0 - nb * DREp + ( nb * DREp ) * ( nb * DREp ) + 0.5 * nb * nb * DRE * DREpp ) + DS + DA
775  + DAOP + DSR;
776 
777  output->deltaT = -Dbb;
778  /********************************************************/
779  }
780 
781  /* for DD model - code partly adapted from TEMPO bnrydd.f */
782  /* also used for MSS model (Wex 1998) - main sequence star orbit - this only has two lines
783  different than DD model - TEMPO bnrymss.f */
784  /* also DDS model and (partial) T2 model (if EPS params not set) from TEMPO2 T2model.C */
785  if ( !strcmp( model, "DD" ) || !strcmp( model, "MSS" ) || !strcmp( model, "DDS" ) || ( !strcmp( model, "T2" ) && eps1 == 0. ) ) {
786  REAL8 u; /* new eccentric anomaly */
787  REAL8 Ae; /* eccentricity parameter */
788  REAL8 DRE; /* Roemer delay + Einstein delay */
789  REAL8 DREp, DREpp; /* see DD eqs 48 - 50 */
790  REAL8 DS; /* Shapiro delay */
791  REAL8 DA; /* aberation caused by pulsar rotation delay */
792  REAL8 DAOP, DSR; /* Kopeikin term delays */
793 
794  REAL8 tt0;
795  /* various variable use during calculation */
796  REAL8 er, eth, an, k;
797  REAL8 orbits, phase;
798  INT4 norbits;
799  REAL8 onemecu, cae, sae;
800  REAL8 alpha, beta, bg;
801  REAL8 anhat, sqr1me2, cume, brace, dlogbr;
802  REAL8 Dbb; /* Delta barbar in DD eq 52 */
803 
804  REAL8 xi; /* parameter for MSS model - the only other one needed */
805  REAL8 sdds = 0.; /* parameter for DDS model */
806 
807  REAL8 su = 0., cu = 0.;
808  REAL8 sw = 0., cw = 0.;
809 
810  KopeikinTerms kt;
811  REAL8 Ck, Sk;
812 
813  /* fprintf(stderr, "You are using the Damour-Deruelle (DD) binary model.\n");*/
814 
815  /* part of code adapted from TEMPO bnrydd.f */
816  an = LAL_TWOPI / Pb;
817  k = wdot / an;
818  xi = xdot / an; /* MSS parameter */
819 
820  tt0 = tb - T0;
821  /* x = x + xdot*tt0; */
822 
823  /* following DDmodel.C from TEMPO2 just set dth, dr, a0 and b0 to 0 */
824  if ( !strcmp( model, "DD" ) ) {
825  dr = 0.;
826  dth = 0.;
827  a0 = 0.;
828  b0 = 0.;
829  }
830 
831  e = e + edot * tt0;
832  er = e * ( 1.0 + dr );
833  eth = e * ( 1.0 + dth );
834 
835  orbits = ( tt0 / Pb ) - 0.5 * ( pbdot + xpbdot ) * ( tt0 / Pb ) * ( tt0 / Pb );
836  norbits = ( INT4 )orbits;
837 
838  if ( orbits < 0.0 ) {
839  norbits--;
840  }
841 
842  phase = LAL_TWOPI * ( orbits - ( REAL8 )norbits );
843 
844  /* compute eccentric anomaly */
845  XLALComputeEccentricAnomaly( phase, e, &u );
846 
847  su = sin( u );
848  cu = cos( u );
849 
850  /* compute Ae as in TEMPO bnrydd.f */
851  onemecu = 1.0 - e * cu;
852  cae = ( cu - e ) / onemecu;
853  sae = sqrt( 1.0 - e * e ) * su / onemecu;
854 
855  Ae = atan2( sae, cae );
856 
857  if ( Ae < 0.0 ) {
858  Ae = Ae + LAL_TWOPI;
859  }
860 
861  Ae = LAL_TWOPI * orbits + Ae - phase;
862 
863  w = w0 + k * Ae; /* add corrections to omega */ /* MSS also uses (om2dot, but not defined) */
864 
865  /* small difference between MSS and DD */
866  if ( !strcmp( model, "MSS" ) ) {
867  x = x + xi * Ae; /* in bnrymss.f they also include a second time derivative of x (x2dot), but
868 this isn't defined for either of the two pulsars currently using this model */
869  } else {
870  x = x + xdot * tt0;
871  }
872 
873  /* now compute time delays as in DD eqs 46 - 52 */
874 
875  /* calculate Einstein and Roemer delay */
876  sw = sin( w );
877  cw = cos( w );
878  alpha = x * sw;
879  beta = x * sqrt( 1.0 - eth * eth ) * cw;
880  bg = beta + lal_gamma;
881  DRE = alpha * ( cu - er ) + bg * su;
882  DREp = -alpha * su + bg * cu;
883  DREpp = -alpha * cu - bg * su;
884  anhat = an / onemecu;
885 
886  /* calculate Shapiro and abberation delays DD eqs 26, 27 */
887  sqr1me2 = sqrt( 1.0 - e * e );
888  cume = cu - e;
889  if ( !strcmp( model, "DDS" ) ) {
890  sdds = 1. - exp( -1.*shapmax );
891  brace = onemecu - sdds * ( sw * cume + sqr1me2 * cw * su );
892  } else {
893  brace = onemecu - s * ( sw * cume + sqr1me2 * cw * su );
894  }
895  dlogbr = log( brace );
896  DS = -2.0 * r * dlogbr;
897 
898  /* this abberation delay is prob fairly small */
899  DA = a0 * ( sin( w + Ae ) + e * sw ) + b0 * ( cos( w + Ae ) + e * cw );
900 
901  /* compute Kopeikin terms */
902  if ( params->kinset && params->komset && ( params->pmra != 0. ||
903  params->pmdec != 0. ) ) {
904  XLALComputeKopeikinTerms( &kt, params, input );
905 
906  Ck = cw * ( cu - er ) - sqrt( 1. - eth * eth ) * sw * su;
907  Sk = sw * ( cu - er ) + sqrt( 1. - eth * eth ) * cw * su;
908 
909  DAOP = ( kt.DK011 + kt.DK012 ) * Ck - ( kt.DK021 + kt.DK022 ) * Sk;
910  DSR = ( kt.DK031 + kt.DK032 ) * Ck + ( kt.DK041 + kt.DK042 ) * Sk;
911  } else {
912  DAOP = 0.;
913  DSR = 0.;
914  }
915 
916  /* timing difference */
917  Dbb = DRE * ( 1.0 - anhat * DREp + anhat * anhat * DREp * DREp + 0.5 * anhat * anhat * DRE * DREpp -
918  0.5 * e * su * anhat * anhat * DRE * DREp / onemecu ) + DS + DA + DAOP + DSR;
919 
920  output->deltaT = -Dbb;
921  }
922 
923  /* for DDGR model */
924 
925  /* for Epstein-Haugan (EH) model - see Haugan, ApJ (1985) eqs 69 and 71 */
926 
927  /* check that the returned value is not a NaN */
928  if ( isnan( output->deltaT ) ) {
930  }
931 }
932 
933 
934 void
936  BinaryPulsarInput *input,
938 {
939  REAL8 dt = 0.; /* binary pulsar deltaT */
940  REAL8 x, xdot; /* x = asini/c */
941  REAL8 w = 0; /* longitude of periastron */
942  REAL8 e, edot; /* eccentricity */
943  REAL8 eps1, eps2;
944  REAL8 eps1dot, eps2dot;
945  REAL8 w0, wdot;
946  REAL8 Pb, pbdot;
947  REAL8 xpbdot;
948  REAL8 T0, Tasc, tb = 0.; /* time parameters */
949 
950  REAL8 s, r; /* Shapiro shape and range params */
951  REAL8 lal_gamma; /* time dilation and grav redshift */
952  REAL8 dr, dth;
953  REAL8 shapmax; /* Shapiro max parameter for DDS model */
954  REAL8 a0, b0; /* abberation parameters */
955  REAL8 pmra, pmdec; /* proper motion parameters */
956 
957  REAL8 m2;
958  const REAL8 c3 = ( REAL8 )LAL_C_SI * ( REAL8 )LAL_C_SI * ( REAL8 )LAL_C_SI;
959 
960  const CHAR *model = PulsarGetStringParam( params, "BINARY" );
961 
962  /* Check input arguments */
963  if ( input == ( BinaryPulsarInput * )NULL ) {
965  }
966 
967  if ( output == ( BinaryPulsarOutput * )NULL ) {
969  }
970 
971  if ( params == ( PulsarParameters * )NULL ) {
973  }
974 
975  if ( ( !strcmp( model, "BT" ) ) &&
976  ( !strcmp( model, "BT1P" ) ) &&
977  ( !strcmp( model, "BT2P" ) ) &&
978  ( !strcmp( model, "BTX" ) ) &&
979  ( !strcmp( model, "ELL1" ) ) &&
980  ( !strcmp( model, "DD" ) ) &&
981  ( !strcmp( model, "DDS" ) ) &&
982  ( !strcmp( model, "MSS" ) ) &&
983  ( !strcmp( model, "T2" ) ) ) {
985  }
986 
987  /* convert certain params to SI units */
988  w0 = PulsarGetREAL8ParamOrZero( params, "OM" );
989  wdot = PulsarGetREAL8ParamOrZero( params, "OMDOT" ); /* wdot in rads/s */
990 
991  Pb = PulsarGetREAL8ParamOrZero( params, "PB" ); /* period in secs */
992  pbdot = PulsarGetREAL8ParamOrZero( params, "PBDOT" );
993 
994  T0 = PulsarGetREAL8ParamOrZero( params, "T0" ); /* these should be in TDB in seconds */
995  Tasc = PulsarGetREAL8ParamOrZero( params, "TASC" );
996 
997  e = PulsarGetREAL8ParamOrZero( params, "ECC" );
998  edot = PulsarGetREAL8ParamOrZero( params, "EDOT" );
999  eps1 = PulsarGetREAL8ParamOrZero( params, "EPS1" );
1000  eps2 = PulsarGetREAL8ParamOrZero( params, "EPS2" );
1001  eps1dot = PulsarGetREAL8ParamOrZero( params, "EPS1DOT" );
1002  eps2dot = PulsarGetREAL8ParamOrZero( params, "EPS2DOT" );
1003 
1004  x = PulsarGetREAL8ParamOrZero( params, "A1" );
1005  xdot = PulsarGetREAL8ParamOrZero( params, "XDOT" );
1006  xpbdot = PulsarGetREAL8ParamOrZero( params, "XPBDOT" );
1007 
1008  lal_gamma = PulsarGetREAL8ParamOrZero( params, "GAMMA" );
1009  s = PulsarGetREAL8ParamOrZero( params, "SINI" ); /* sin i */
1010  dr = PulsarGetREAL8ParamOrZero( params, "DR" );
1011  dth = PulsarGetREAL8ParamOrZero( params, "DTHETA" );
1012  shapmax = PulsarGetREAL8ParamOrZero( params, "SHAPMAX" );
1013 
1014  a0 = PulsarGetREAL8ParamOrZero( params, "A0" );
1015  b0 = PulsarGetREAL8ParamOrZero( params, "B0" );
1016 
1017  m2 = PulsarGetREAL8ParamOrZero( params, "M2" );
1018 
1019  pmra = PulsarGetREAL8ParamOrZero( params, "PMRA" );
1020  pmdec = PulsarGetREAL8ParamOrZero( params, "PMDEC" );
1021 
1022  /* Shapiro range parameter r defined as Gm2/c^3 (secs) */
1023  r = LAL_G_SI * m2 / c3;
1024 
1025  /* if T0 is not defined, but Tasc is */
1026  if ( T0 == 0.0 && Tasc != 0.0 && eps1 == 0.0 && eps2 == 0.0 ) {
1027  REAL8 fe, uasc, Dt; /* see TEMPO tasc2t0.f */
1028 
1029  fe = sqrt( ( 1.0 - e ) / ( 1.0 + e ) );
1030  uasc = 2.0 * atan( fe * tan( w0 / 2.0 ) );
1031  Dt = ( Pb / LAL_TWOPI ) * ( uasc - e * sin( uasc ) );
1032 
1033  T0 = Tasc + Dt;
1034  }
1035 
1036  /* set time at which to calculate the binary time delay */
1037  tb = input->tb;
1038 
1039  /* for BT, BT1P and BT2P models (and BTX model, but only for one orbit) */
1040  if ( strstr( model, "BT" ) != NULL ) {
1041  REAL8 tt0;
1042  REAL8 orbits = 0.;
1043  INT4 norbits = 0;
1044  REAL8 phase; /* same as mean anomaly */
1045  REAL8 u = 0.0; /* eccentric anomaly */
1046 
1047  INT4 nplanets = 1; /* number of orbiting bodies in system */
1048  INT4 i = 1, j = 1;
1049  REAL8 fac = 1.; /* factor in front of fb coefficients */
1050 
1051  REAL8 su = 0., cu = 0.;
1052  REAL8 sw = 0., cw = 0.;
1053 
1054  /* work out number of orbits i.e. have we got a BT1P or BT2P model */
1055  if ( !strcmp( model, "BT1P" ) ) {
1056  nplanets = 2;
1057  }
1058  if ( !strcmp( model, "BT2P" ) ) {
1059  nplanets = 3;
1060  }
1061 
1062  for ( i = 1 ; i < nplanets + 1 ; i++ ) {
1063 
1064  /* set some vars for bnrybt.f (TEMPO) method */
1065  /*REAL8 tt;
1066  REAL8 som;
1067  REAL8 com;
1068  REAL8 alpha, beta;*/
1069  /*REAL8 q, r, s;*/
1070 
1071  /*fprintf(stderr, "You are using the Blandford-Teukolsky (BT) binary model.\n");*/
1072 
1073  if ( i == 2 ) {
1074  T0 = PulsarGetREAL8ParamOrZero( params, "T0_2" );
1075  w0 = PulsarGetREAL8ParamOrZero( params, "OM_2" );
1076  x = PulsarGetREAL8ParamOrZero( params, "A1_2" );
1077  e = PulsarGetREAL8ParamOrZero( params, "ECC_2" );
1078  Pb = PulsarGetREAL8ParamOrZero( params, "PB_2" );
1079  } else if ( i == 3 ) {
1080  T0 = PulsarGetREAL8ParamOrZero( params, "T0_3" );
1081  w0 = PulsarGetREAL8ParamOrZero( params, "OM_3" );
1082  x = PulsarGetREAL8ParamOrZero( params, "A1_3" );
1083  e = PulsarGetREAL8ParamOrZero( params, "ECC_3" );
1084  Pb = PulsarGetREAL8ParamOrZero( params, "PB_3" );
1085  }
1086 
1087  tt0 = tb - T0;
1088 
1089  /* only do relativistic corrections for first orbit */
1090  if ( i == 1 ) {
1091  x = x + xdot * tt0;
1092  e = e + edot * tt0;
1093  w = w0 + wdot * tt0; /* calculate w */
1094 
1095  if ( !strcmp( model, "BTX" ) && PulsarCheckParam( params, "FB" ) ) {
1096  const REAL8Vector *fb = PulsarGetREAL8VectorParam( params, "FB" );
1097 
1098  fac = 1.;
1099  for ( j = 1 ; j < ( INT4 )fb->length + 1; j++ ) {
1100  fac /= ( REAL8 )j;
1101  orbits += fac * fb->data[j - 1] * pow( tt0, j );
1102  }
1103  } else {
1104  orbits = tt0 / Pb - 0.5 * ( pbdot + xpbdot ) * ( tt0 / Pb ) * ( tt0 / Pb );
1105  }
1106  } else {
1107  orbits = tt0 / Pb;
1108  }
1109 
1110  norbits = ( INT4 )orbits;
1111 
1112  if ( orbits < 0. ) {
1113  norbits--;
1114  }
1115 
1116  phase = LAL_TWOPI * ( orbits - ( REAL8 )norbits ); /* called phase in TEMPO */
1117 
1118  /* compute eccentric anomaly */
1119  XLALComputeEccentricAnomaly( phase, e, &u );
1120 
1121  su = sin( u );
1122  cu = cos( u );
1123 
1124  /*fprintf(stderr, "Eccentric anomaly = %f, phase = %f.\n", u, phase);*/
1125  sw = sin( w );
1126  cw = cos( w );
1127 
1128  /* see eq 5 of Taylor and Weisberg (1989) */
1129  /**********************************************************/
1130  if ( !strcmp( model, "BTX" ) ) {
1131  REAL8 fb0 = 0.;
1132  if ( PulsarCheckParam( params, "FB" ) ) {
1133  const REAL8Vector *fb = PulsarGetREAL8VectorParam( params, "FB" );
1134  fb0 = fb->data[0];
1135  }
1136  /* dt += (x*sin(w)*(cos(u)-e) + (x*cos(w)*sqrt(1.0-e*e) +
1137  lal_gamma)*sin(u))*(1.0 - params->fb[0]*(x*cos(w)*sqrt(1.0 -
1138  e*e)*cos(u) - x*sin(w)*sin(u))/(1.0 - e*cos(u))); */
1139  dt += ( x * sw * ( cu - e ) + ( x * cw * sqrt( 1.0 - e * e ) +
1140  lal_gamma ) * su ) * ( 1.0 - LAL_TWOPI * fb0 * ( x * cw * sqrt( 1.0 -
1141  e * e ) * cu - x * sw * su ) / ( 1.0 - e * cu ) );
1142  } else {
1143  /* dt += (x*sin(w)*(cos(u)-e) + (x*cos(w)*sqrt(1.0-e*e) +
1144  lal_gamma)*sin(u))*(1.0 - (LAL_TWOPI/Pb)*(x*cos(w)*sqrt(1.0 -
1145  e*e)*cos(u) - x*sin(w)*sin(u))/(1.0 - e*cos(u))); */
1146  dt += ( x * sw * ( cu - e ) + ( x * cw * sqrt( 1.0 - e * e ) +
1147  lal_gamma ) * su ) * ( 1.0 - ( LAL_TWOPI / Pb ) * ( x * cw * sqrt( 1.0 -
1148  e * e ) * cu - x * sw * su ) / ( 1.0 - e * cu ) );
1149  }
1150  /**********************************************************/
1151  }
1152 
1153  /* use method from Taylor etal 1976 ApJ Lett and used in bnrybt.f */
1154  /**********************************************************/
1155  /*tt = 1.0-e*e;
1156  som = sin(w);
1157  com = cos(w);
1158  alpha = x*som;
1159  beta = x*com*sqrt(tt);
1160  q = alpha*(cos(u)-e) + (beta+lal_gamma)*sin(u);
1161  r = -alpha*sin(u) + beta*cos(u);
1162  s = 1.0/(1.0-e*cos(u));
1163  dt = -(-q+(LAL_TWOPI/Pb)*q*r*s);*/
1164  /**********************************************************/
1165  /* There appears to be NO difference between either method */
1166 
1167  output->deltaT = -dt;
1168  }
1169 
1170  /* for ELL1 model (low eccentricity orbits so use eps1 and eps2) */
1171  /* see Appendix A, Ch. Lange etal, MNRAS (2001) (also accept T2 model if
1172  eps values are set - this will include Kopeikin terms if necessary) */
1173  if ( !strcmp( model, "ELL1" ) || ( !strcmp( model, "T2" ) && eps1 != 0. ) ) {
1174  REAL8 nb;
1175  REAL8 tt0;
1176  REAL8 w_int; /* omega internal to this model */
1177  REAL8 orbits, phase;
1178  INT4 norbits;
1179  REAL8 e1, e2, ecc;
1180  REAL8 DRE, DREp, DREpp; /* Roemer and Einstein delays (cf DD) */
1181  REAL8 dlogbr;
1182  REAL8 DS, DA; /* Shapiro delay and Abberation delay terms */
1183  REAL8 Dbb;
1184  REAL8 DAOP, DSR; /* Kopeikin delay terms */
1185  REAL8 fac = 1.; /* factor in front of fb coefficients */
1186 
1187  KopeikinTerms kt;
1188  REAL8 Ck, Sk;
1189 
1190  REAL8 sp = 0., cp = 0., s2p = 0., c2p = 0.;
1191 
1192  /* fprintf(stderr, "You are using the ELL1 low eccentricity orbit model.\n");*/
1193 
1194  /*********************************************************/
1195  /* CORRECT CODE (as in TEMPO bnryell1.f) FROM HERE */
1196 
1197  ecc = sqrt( eps1 * eps1 + eps2 * eps2 );
1198 
1199  /* if Tasc is not defined convert T0 */
1200  if ( Tasc == 0.0 && T0 != 0.0 ) {
1201  REAL8 fe, uasc, Dt; /* see TEMPO tasc2t0.f */
1202 
1203  fe = sqrt( ( 1.0 - ecc ) / ( 1.0 + ecc ) );
1204  uasc = 2.0 * atan( fe * tan( w0 / 2.0 ) );
1205  Dt = ( Pb / LAL_TWOPI ) * ( uasc - ecc * sin( uasc ) );
1206 
1207  /* rearrange from what's in tasc2t0.f */
1208  Tasc = T0 - Dt;
1209  }
1210 
1211  tt0 = tb - Tasc;
1212 
1213  /* handle higher orbital frequency derivatives if present */
1214  if ( PulsarCheckParam( params, "FB" ) ) {
1215  const REAL8Vector *fb = PulsarGetREAL8VectorParam( params, "FB" );
1216 
1217  /* set period from first orbital frequency value */
1218  Pb = 1. / fb->data[0];
1219  orbits = tt0 / Pb;
1220 
1221  fac = 1.;
1222  for ( UINT4 j = 1 ; j < fb->length; j++ ) {
1223  fac /= ( REAL8 )( j + 1 );
1224  orbits += fac * fb->data[j] * pow( tt0, j + 1 );
1225  }
1226  } else {
1227  orbits = tt0 / Pb - 0.5 * ( pbdot + xpbdot ) * ( tt0 / Pb ) * ( tt0 / Pb );
1228  }
1229 
1230  nb = LAL_TWOPI / Pb;
1231 
1232  norbits = ( INT4 )orbits;
1233  if ( orbits < 0.0 ) {
1234  norbits--;
1235  }
1236 
1237  phase = LAL_TWOPI * ( orbits - ( REAL8 )norbits );
1238 
1239  x = x + xdot * tt0;
1240 
1241  /* depending on whether we have eps derivs or w time derivs calculate e1 and e2 accordingly */
1242  if ( eps1dot != 0. || eps2dot != 0. ) {
1243  e1 = eps1 + eps1dot * tt0;
1244  e2 = eps2 + eps2dot * tt0;
1245  } else {
1246  ecc = sqrt( eps1 * eps1 + eps2 * eps2 );
1247  ecc += edot * tt0;
1248  w_int = atan2( eps1, eps2 );
1249  w_int = w_int + wdot * tt0;
1250 
1251  e1 = ecc * sin( w_int );
1252  e2 = ecc * cos( w_int );
1253  }
1254 
1255  //sin_cos_LUT(&sp, &cp, phase);
1256  //sin_cos_LUT(&s2p, &c2p, 2.*phase);
1257  sp = sin( phase );
1258  cp = cos( phase );
1259  s2p = sin( 2.*phase );
1260  c2p = cos( 2.*phase );
1261 
1262  /* this timing delay (Roemer + Einstein) should be most important in most cases */
1263  /* DRE = x*(sin(phase)-0.5*(e1*cos(2.0*phase)-e2*sin(2.0*phase)));
1264  DREp = x*cos(phase);
1265  DREpp = -x*sin(phase); */
1266  DRE = x * ( sp - 0.5 * ( e1 * c2p - e2 * s2p ) );
1267  DREp = x * cp;
1268  DREpp = -x * sp;
1269 
1270  /* these params will normally be negligable */
1271  dlogbr = log( 1.0 - s * sp );
1272  DS = -2.0 * r * dlogbr;
1273  DA = a0 * sp + b0 * cp;
1274 
1275  /* compute Kopeikin terms */
1276  if ( PulsarCheckParam( params, "KIN" ) && PulsarCheckParam( params, "KOM" ) && ( pmra != 0. || pmdec != 0. ) ) {
1277  XLALComputeKopeikinTermsNew( &kt, params, input );
1278 
1279  Ck = sp - 0.5 * ( e1 * c2p - e2 * s2p );
1280  Sk = cp + 0.5 * ( e2 * c2p + e1 * s2p );
1281 
1282  DAOP = ( kt.DK011 + kt.DK012 ) * Ck - ( kt.DK021 + kt.DK022 ) * Sk;
1283  DSR = ( kt.DK031 + kt.DK032 ) * Ck + ( kt.DK041 + kt.DK042 ) * Sk;
1284  } else {
1285  DAOP = 0.;
1286  DSR = 0.;
1287  }
1288 
1289  Dbb = DRE * ( 1.0 - nb * DREp + ( nb * DREp ) * ( nb * DREp ) + 0.5 * nb * nb * DRE * DREpp ) + DS + DA
1290  + DAOP + DSR;
1291 
1292  output->deltaT = -Dbb;
1293  /********************************************************/
1294  }
1295 
1296  /* for DD model - code partly adapted from TEMPO bnrydd.f */
1297  /* also used for MSS model (Wex 1998) - main sequence star orbit - this only has two lines
1298  different than DD model - TEMPO bnrymss.f */
1299  /* also DDS model and (partial) T2 model (if EPS params not set) from TEMPO2 T2model.C */
1300  if ( !strcmp( model, "DD" ) || !strcmp( model, "MSS" ) || !strcmp( model, "DDS" ) || ( !strcmp( model, "T2" ) && eps1 == 0. ) ) {
1301  REAL8 u; /* new eccentric anomaly */
1302  REAL8 Ae; /* eccentricity parameter */
1303  REAL8 DRE; /* Roemer delay + Einstein delay */
1304  REAL8 DREp, DREpp; /* see DD eqs 48 - 50 */
1305  REAL8 DS; /* Shapiro delay */
1306  REAL8 DA; /* aberation caused by pulsar rotation delay */
1307  REAL8 DAOP, DSR; /* Kopeikin term delays */
1308 
1309  REAL8 tt0;
1310  /* various variable use during calculation */
1311  REAL8 er, eth, an, k;
1312  REAL8 orbits, phase;
1313  INT4 norbits;
1314  REAL8 onemecu, cae, sae;
1315  REAL8 alpha, beta, bg;
1316  REAL8 anhat, sqr1me2, cume, brace, dlogbr;
1317  REAL8 Dbb; /* Delta barbar in DD eq 52 */
1318 
1319  REAL8 xi; /* parameter for MSS model - the only other one needed */
1320  REAL8 sdds = 0.; /* parameter for DDS model */
1321 
1322  REAL8 su = 0., cu = 0.;
1323  REAL8 sw = 0., cw = 0.;
1324 
1325  KopeikinTerms kt;
1326  REAL8 Ck, Sk;
1327 
1328  /* fprintf(stderr, "You are using the Damour-Deruelle (DD) binary model.\n");*/
1329 
1330  /* part of code adapted from TEMPO bnrydd.f */
1331  an = LAL_TWOPI / Pb;
1332  k = wdot / an;
1333  xi = xdot / an; /* MSS parameter */
1334 
1335  tt0 = tb - T0;
1336  /* x = x + xdot*tt0; */
1337 
1338  /* following DDmodel.C from TEMPO2 just set dth, dr, a0 and b0 to 0 */
1339  if ( !strcmp( model, "DD" ) ) {
1340  dr = 0.;
1341  dth = 0.;
1342  a0 = 0.;
1343  b0 = 0.;
1344  }
1345 
1346  e = e + edot * tt0;
1347  er = e * ( 1.0 + dr );
1348  eth = e * ( 1.0 + dth );
1349 
1350  orbits = ( tt0 / Pb ) - 0.5 * ( pbdot + xpbdot ) * ( tt0 / Pb ) * ( tt0 / Pb );
1351  norbits = ( INT4 )orbits;
1352 
1353  if ( orbits < 0.0 ) {
1354  norbits--;
1355  }
1356 
1357  phase = LAL_TWOPI * ( orbits - ( REAL8 )norbits );
1358 
1359  /* compute eccentric anomaly */
1360  XLALComputeEccentricAnomaly( phase, e, &u );
1361 
1362  su = sin( u );
1363  cu = cos( u );
1364 
1365  /* compute Ae as in TEMPO bnrydd.f */
1366  onemecu = 1.0 - e * cu;
1367  cae = ( cu - e ) / onemecu;
1368  sae = sqrt( 1.0 - e * e ) * su / onemecu;
1369 
1370  Ae = atan2( sae, cae );
1371 
1372  if ( Ae < 0.0 ) {
1373  Ae = Ae + LAL_TWOPI;
1374  }
1375 
1376  Ae = LAL_TWOPI * orbits + Ae - phase;
1377 
1378  w = w0 + k * Ae; /* add corrections to omega */ /* MSS also uses (om2dot, but not defined) */
1379 
1380  /* small difference between MSS and DD */
1381  if ( !strcmp( model, "MSS" ) ) {
1382  x = x + xi * Ae; /* in bnrymss.f they also include a second time derivative of x (x2dot), but
1383 this isn't defined for either of the two pulsars currently using this model */
1384  } else {
1385  x = x + xdot * tt0;
1386  }
1387 
1388  /* now compute time delays as in DD eqs 46 - 52 */
1389 
1390  /* calculate Einstein and Roemer delay */
1391  sw = sin( w );
1392  cw = cos( w );
1393  alpha = x * sw;
1394  beta = x * sqrt( 1.0 - eth * eth ) * cw;
1395  bg = beta + lal_gamma;
1396  DRE = alpha * ( cu - er ) + bg * su;
1397  DREp = -alpha * su + bg * cu;
1398  DREpp = -alpha * cu - bg * su;
1399  anhat = an / onemecu;
1400 
1401  /* calculate Shapiro and abberation delays DD eqs 26, 27 */
1402  sqr1me2 = sqrt( 1.0 - e * e );
1403  cume = cu - e;
1404  if ( !strcmp( model, "DDS" ) ) {
1405  sdds = 1. - exp( -1.*shapmax );
1406  brace = onemecu - sdds * ( sw * cume + sqr1me2 * cw * su );
1407  } else {
1408  brace = onemecu - s * ( sw * cume + sqr1me2 * cw * su );
1409  }
1410  dlogbr = log( brace );
1411  DS = -2.0 * r * dlogbr;
1412 
1413  /* this abberation delay is prob fairly small */
1414  DA = a0 * ( sin( w + Ae ) + e * sw ) + b0 * ( cos( w + Ae ) + e * cw );
1415 
1416  /* compute Kopeikin terms */
1417  if ( PulsarCheckParam( params, "KIN" ) && PulsarCheckParam( params, "KOM" ) && ( pmra != 0. || pmdec != 0. ) ) {
1418  XLALComputeKopeikinTermsNew( &kt, params, input );
1419 
1420  Ck = cw * ( cu - er ) - sqrt( 1. - eth * eth ) * sw * su;
1421  Sk = sw * ( cu - er ) + sqrt( 1. - eth * eth ) * cw * su;
1422 
1423  DAOP = ( kt.DK011 + kt.DK012 ) * Ck - ( kt.DK021 + kt.DK022 ) * Sk;
1424  DSR = ( kt.DK031 + kt.DK032 ) * Ck + ( kt.DK041 + kt.DK042 ) * Sk;
1425  } else {
1426  DAOP = 0.;
1427  DSR = 0.;
1428  }
1429 
1430  /* timing difference */
1431  Dbb = DRE * ( 1.0 - anhat * DREp + anhat * anhat * DREp * DREp + 0.5 * anhat * anhat * DRE * DREpp -
1432  0.5 * e * su * anhat * anhat * DRE * DREp / onemecu ) + DS + DA + DAOP + DSR;
1433 
1434  output->deltaT = -Dbb;
1435  }
1436 
1437  /* for DDGR model */
1438 
1439  /* for Epstein-Haugan (EH) model - see Haugan, ApJ (1985) eqs 69 and 71 */
1440 
1441  /* check that the returned value is not a NaN */
1442  if ( isnan( output->deltaT ) ) {
1444  }
1445 
1446 }
1447 
void XLALBinaryPulsarDeltaTNew(BinaryPulsarOutput *output, BinaryPulsarInput *input, PulsarParameters *params)
function to calculate the binary system delay using new parameter structure
void XLALComputeEccentricAnomaly(REAL8 phase, REAL8 ecc, REAL8 *u)
XLAL function to compute the eccentric anomaly iteratively from Kelper's equation.
void XLALComputeKopeikinTerms(KopeikinTerms *kop, BinaryPulsarParams *params, BinaryPulsarInput *in)
XLAL function to compute Kopeikin terms that include the effect of binary orbital parameters of paral...
#define AULTSC
void XLALComputeKopeikinTermsNew(KopeikinTerms *kop, PulsarParameters *params, BinaryPulsarInput *in)
void LALBinaryPulsarDeltaT(LALStatus *status, BinaryPulsarOutput *output, BinaryPulsarInput *input, BinaryPulsarParams *params)
Calculate the binary system time delay using the pulsar parameters in params.
void XLALBinaryPulsarDeltaT(BinaryPulsarOutput *output, BinaryPulsarInput *input, BinaryPulsarParams *params)
XLAL function to compute the binary time delay.
#define BINARYPULSARTIMINGH_ENAN
#define BINARYPULSARTIMINGH_MSGENULLPARAMS
#define BINARYPULSARTIMINGH_ENULLOUTPUT
#define BINARYPULSARTIMINGH_ENULLINPUT
#define BINARYPULSARTIMINGH_ENULLPARAMS
#define BINARYPULSARTIMINGH_MSGENULLOUTPUT
#define BINARYPULSARTIMINGH_ENULLBINARYMODEL
#define BINARYPULSARTIMINGH_MSGNULLBINARYMODEL
#define BINARYPULSARTIMINGH_MSGENULLINPUT
#define __func__
log an I/O error, i.e.
int j
int k
const double b0
#define ATTATCHSTATUSPTR(statusptr)
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
const REAL8Vector * PulsarGetREAL8VectorParam(const PulsarParameters *pars, const CHAR *name)
Return a REAL8Vector parameter.
REAL8 PulsarGetREAL8ParamOrZero(const PulsarParameters *pars, const CHAR *name)
Return a REAL8 parameter if it exists, otherwise return zero.
int PulsarCheckParam(const PulsarParameters *pars, const CHAR *name)
Check for the existence of the parameter name in the PulsarParameters structure.
const CHAR * PulsarGetStringParam(const PulsarParameters *pars, const CHAR *name)
Return a string parameter.
REAL8 PulsarGetREAL8Param(const PulsarParameters *pars, const CHAR *name)
Return a REAL8 parameter.
int s
double e
const double u
const double w
#define LAL_TWOPI
#define LAL_G_SI
double REAL8
char CHAR
uint32_t UINT4
int32_t INT4
static const INT4 r
#define XLAL_ERROR_VOID(...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_EINVAL
m2
int T0
double alpha
structure containing the input parameters for the binary delay function
REAL8 tb
Time of arrival (TOA) at the SSB.
EarthState earth
The current Earth state (for e.g.
structure containing the output parameters for the binary delay function
A structure to contain all pulsar parameters and associated errors.
REAL8 posNow[3]
Cartesian coords of Earth's center at tgps, extrapolated from JPL DE405 ephemeris; units= sec.
structure containing the Kopeikin terms
The PulsarParameters structure to contain a set of pulsar parameters.
REAL8 * data
double ra
double dec
double m2