LALPulsar  6.1.0.1-b72065a
LALBarycenter.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Miroslav Shaltev, R Prix
3 * Copyright (C) 2007 Curt Cutler, Jolien Creighton, Reinhard Prix, Teviet Creighton
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with with program; see the file COPYING. If not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301 USA
19 */
20 
21 #include <lal/Date.h>
22 #include <lal/LALBarycenter.h>
23 
24 #define OBLQ 0.40909280422232891e0; /* obliquity of ecliptic at JD 245145.0* in radians */;
25 
26 /// ---------- internal buffer type for optimized Barycentering function ----------
27 typedef struct tagfixed_sky {
28  REAL8 sinAlpha; /// sin(alpha)
29  REAL8 cosAlpha; /// cos(alpha)
30  REAL8 sinDelta; /// sin(delta)
31  REAL8 cosDelta; /// cos(delta)
32  REAL8 n[3]; /// unit vector pointing from SSB to the source, in J2000 Cartesian coords, 0=x,1=y,2=z
33 } fixed_sky_t;
34 
35 typedef struct tagfixed_site {
36  REAL8 rd; /// distance 'rd' from center of Earth, in light seconds
37  REAL8 longitude; /// geocentric (not geodetic!!) longitude of detector vertex
38  REAL8 latitude; /// geocentric latitude of detector vertex
39  REAL8 sinLat; /// sin(latitude)
40  REAL8 cosLat; /// cos(latitude);
41  REAL8 rd_sinLat; /// rd * sin(latitude)
42  REAL8 rd_cosLat; /// rd * cos(latitude)
43 } fixed_site_t;
44 
46  REAL8 alpha; /// buffered sky-location: right-ascension in rad
47  REAL8 delta; /// buffered sky-location: declination in rad
48  fixed_sky_t fixed_sky; /// fixed-sky buffered quantities
49 
50  LALDetector site; /// buffered detector site
51  fixed_site_t fixed_site; /// fixed-site buffered quantities
52 
53  BOOLEAN active; /// switch set on TRUE of buffer has been filled
54 }; // struct tagBarycenterBuffer
55 
56 /* Internal functions */
57 static void precessionMatrix( REAL8 prn[3][3], REAL8 mjd, REAL8 dpsi, REAL8 deps );
58 static void observatoryEarth( REAL8 obsearth[3], const LALDetector det, const LIGOTimeGPS *tgps, REAL8 gmst, REAL8 dpsi, REAL8 deps );
59 
60 /// \addtogroup LALBarycenter_h
61 /// @{
62 
63 /**
64  * \author Curt Cutler
65  * \brief Computes the position and orientation of the Earth, at some arrival time
66  * \f$ t_a \f$ , specified <tt>LIGOTimeGPS</tt> input structure.
67  *
68  * The Einstein delay is also calculated. The results are stored in the
69  * <tt>EarthState</tt> output structure, which can then be fed as input to
70  * <tt>LALBarycenter()</tt>.
71  * The idea is that <tt>LALBarycenterEarth()</tt> calculates quantities that
72  * are independent of the source location and detector position
73  * on Earth. Thus this function is called ONCE for every desired
74  * arrival time; the results are then re-used as one steps around the
75  * sky (and/or changes detector) at that time.
76  */
77 int
78 XLALBarycenterEarth( EarthState *earth, /**< [out] the earth's state at time tGPS */
79  const LIGOTimeGPS *tGPS, /**< [in] GPS time tgps */
80  const EphemerisData *edat ) /**< [in] ephemeris-files */
81 {
82  REAL8 tgps[2]; /*I convert from two-integer representation to
83  two REAL8s (just because I initially wrote my code for
84  REAL8s). GPS time(sec) = tgps[0] + 1.e-9*tgps[1] */
85 
86  /*int ihour; most recent hour to current time, tGPS,
87  in look-up table */
88  /*REAL8 t0,t0hr; */
89 
90  REAL8 t0e; /*time since first entry in Earth ephem. table */
91  INT4 ientryE; /*entry in look-up table closest to current time, tGPS */
92 
93  REAL8 tinitE; /*time (GPS) of first entry in Earth ephem table*/
94  REAL8 tdiffE; /*current time tGPS minus time of nearest entry
95  in Earth ephem look-up table */
96  REAL8 tdiff2E; /*tdiff2=tdiffE*tdiffE */
97  /*next entries are same as above, but for Sun table */
98  REAL8 t0s;
99  INT4 ientryS;
100  REAL8 tinitS;
101  REAL8 tdiffS;
102  REAL8 tdiff2S;
103 
104  INT4 j; /*dummy index */
105 
106  earth->ttype = TIMECORRECTION_ORIGINAL; /* using the original XLALBarycenterEarth function */
107 
108  /* check input */
109  if ( !earth || !tGPS || !edat || !edat->ephemE || !edat->ephemS ) {
110  XLALPrintError( "%s: invalid NULL input 'earth', 'tGPS', 'edat', 'edat->ephemE' or 'edat->ephemS'\n", __func__ );
112  }
113 
114  tgps[0] = ( REAL8 )tGPS->gpsSeconds; /*convert from INT4 to REAL8 */
115  tgps[1] = ( REAL8 )tGPS->gpsNanoSeconds;
116 
117  tinitE = edat->ephemE[0].gps;
118  tinitS = edat->ephemS[0].gps;
119 
120  t0e = tgps[0] - tinitE;
121  ientryE = floor( ( t0e / edat->dtEtable ) + 0.5e0 ); /*finding Earth table entry
122  closest to arrival time*/
123  t0s = tgps[0] - tinitS;
124  ientryS = floor( ( t0s / edat->dtStable ) + 0.5e0 ); /*finding Sun table entry
125  closest to arrival time*/
126 
127  /*Making sure tgps is within earth and sun ephemeris arrays*/
128 
129  if ( ( ientryE < 0 ) || ( ientryE >= edat->nentriesE ) ) {
130  XLALPrintError( "%s: input GPS time %f outside of Earth ephem range [%f, %f]\n", __func__, tgps[0], tinitE, tinitE + edat->nentriesE * edat->dtEtable );
132  }
133  if ( ( ientryS < 0 ) || ( ientryS >= edat->nentriesS ) ) {
134  XLALPrintError( "%s: input GPS time %f outside of Sun ephem range [%f, %f]\n", __func__, tgps[0], tinitS, tinitS + edat->nentriesS * edat->dtStable );
136  }
137 
138  tdiffE = t0e - edat->dtEtable * ientryE + tgps[1] * 1.e-9; /*tdiff is arrival
139  time minus closest Earth table entry; tdiff can be pos. or neg. */
140  tdiff2E = tdiffE * tdiffE;
141 
142  tdiffS = t0s - edat->dtStable * ientryS + tgps[1] * 1.e-9; /*same for Sun*/
143  tdiff2S = tdiffS * tdiffS;
144 
145 
146  /********************************************************************
147  *Calucate position and vel. of center of Earth.
148  *We extrapolate from a table produced using JPL DE405 ephemeris.
149  *---------------------------------------------------------------------
150  */
151  {
152 
153  REAL8 *pos = edat->ephemE[ientryE].pos; /*Cartesian coords of center of Earth
154  from DE405 ephem, in sec. 0=x,1=y,2=z */
155  REAL8 *vel = edat->ephemE[ientryE].vel;
156  REAL8 *acc = edat->ephemE[ientryE].acc;
157 
158  for ( j = 0; j < 3; j++ ) {
159  earth->posNow[j] = pos[j] + vel[j] * tdiffE + 0.5 * acc[j] * tdiff2E;
160  earth->velNow[j] = vel[j] + acc[j] * tdiffE;
161  }
162  }
163 
164  /********************************************************************
165  * Now calculating Earth's rotational state.
166  *---------------------------------------------------------------------
167  */
168  {
169  INT2 leapsSince2000; /*number of leap secs added to UTC calendar since
170  Jan 1, 2000 00:00:00 UTC; leap is a NEGATIVE number
171  for dates before Jan 1, 2000. */
172 
173  REAL8 tu0JC; /*time elapsed on UT1 clock (in Julian centuries)
174  between Jan 1.5 2000 (= J2000 epoch)
175  and midnight before gps[0,j] */
176 
177  REAL8 tuJC; /*time elapsed on UT1 clock (in Julian centuries)
178  between Jan 1.5 2000 (= J2000 epoch)
179  and the present time (tGPS) */
180 
181  INT4 tuInt; /*number of full seconds (integer) on elapsed
182  on UT1 clock from Jan 1, 2000 00:00:00 UTC to present*/
183  REAL8 dtu; /*see comments below*/
184 
185  REAL8 gmst; /*Greenwich mean sidereal time at present (tGPS), in sec */
186  REAL8 gmst0; /*Greenwich mean sidereal time at prev. midnight, in sec */
187  REAL8 gmstRad; /*gmst, but in radians*/
188 
189  INT4 ut1secSince1Jan2000, fullUt1days;
190  REAL8 daysSinceJ2000;
191  REAL8 eps0 = OBLQ; /*obliquity of ecliptic at JD 245145.0*/
192 
193  leapsSince2000 = 0; /*right # for Jan. 1, 2000 */
194  leapsSince2000 = XLALGPSLeapSeconds( tGPS->gpsSeconds ) - 13;
195  {
196  INT4 err = xlalErrno;
197  if ( err != XLAL_SUCCESS ) {
198  XLALPrintError( "%s: XLALGPSLeapSeconds (%d) failed.\n", __func__, tGPS->gpsSeconds );
200  }
201  }
202 
203  tuInt = tGPS->gpsSeconds - 630720013; /*first subtract off value
204  of gps clock at Jan 1, 2000 00:00:00 UTC */
205 
206  ut1secSince1Jan2000 = tuInt - leapsSince2000; /*next subtract
207  off # leap secs added to UTC calendar since Jan 1, 2000 00:00:00 UTC */
208  tuJC = ( ut1secSince1Jan2000 + tgps[1] * 1.e-9 - 43200 ) / ( 8.64e4 * 36525 );
209  /*UT1 time elapsed, in Julian centuries, since Jan 1.5 2000
210  (= J2000 epoch) and pulse arrival time*/
211 
212  fullUt1days = floor( ut1secSince1Jan2000 / 8.64e4 );/*full days on ut1 clock
213  since Jan 1, 2000 00:00:00 UTC */
214 
215 
216  tu0JC = ( fullUt1days - 0.5e0 ) / 36525.0; /* UT1 time elapsed,
217  in Julian centuries between Jan 1.5 2000 (= J2000 epoch)
218  and midnight before gps[0,j] */
219 
220  dtu = tuJC - tu0JC; /*time, in Jul. centuries, between pulse arrival time and previous midnight (UT1) */
221 
222  daysSinceJ2000 = ( tuInt - 43200 ) / 8.64e4; /*days(not int) on GPS
223  (or TAI,etc.) clock since J2000 */
224 
225  /*----------------------------------------------------------------------
226  *in below formula for gmst0 & gmst, on rhs we SHOULD use time elapsed
227  * in UT1, but instead we insert elapsed in UTC. This will lead to
228  * errors in tdb of order 1 microsec.
229  *----------------------------------------------------------------------
230  */
231 
232  gmst0 = 24110.54841e0 + tu0JC * ( 8640184.812866e0 + tu0JC * ( 0.093104e0
233  - tu0JC * 6.2e-6 ) ); /*formula for Greenwich mean sidereal time
234  on p.50 of Explanatory Supp. to Ast Alm. ...
235  gmst unit is sec, where 2pi rad = 24*60*60sec */
236 
237  /*-----------------------------------------------------------------------
238  *Explan of tu0JC*8640184.812866e0 term: when tu0JC0=0.01 Julian centuries
239  *(= 1 year), Earth has spun an extra 86401.84 sec (approx one revolution)
240  *with respect to the stars.
241  *
242  *Note: this way of organizing calc of gmst was stolen from TEMPO;
243  *see subroutine lmst (= local mean sidereal time) .
244  *------------------------------------------------------------------------
245  */
246 
247 
248  gmst = gmst0 + dtu * ( 8.64e4 * 36525 + 8640184.812866e0
249  + 0.093104e0 * ( tuJC + tu0JC )
250  - 6.2e-6 * ( tuJC * tuJC + tuJC * tu0JC + tu0JC * tu0JC ) );
251 
252  gmstRad = gmst * LAL_PI / 43200;
253 
254  earth->gmstRad = gmstRad;
255 
256  /*------------------------------------------------------------------------
257  *Now calculating 3 terms, describing lunisolar precession;
258  *see Eqs. 3.212 on pp. 104-5 in Explanatory Supp.
259  *-------------------------------------------------------------------------
260  */
261 
262  earth->tzeA = tuJC * ( 2306.2181e0 + ( 0.30188e0 + 0.017998e0 * tuJC ) * tuJC )
263  * LAL_PI / 6.48e5;
264 
265  earth->zA = tuJC * ( 2306.2181e0 + ( 1.09468e0 + 0.018203e0 * tuJC ) * tuJC )
266  * LAL_PI / 6.48e5;
267 
268  earth->thetaA = tuJC * ( 2004.3109e0 - ( 0.42665e0 + 0.041833 * tuJC ) * tuJC )
269  * LAL_PI / 6.48e5;
270 
271  /*--------------------------------------------------------------------------
272  * Now adding approx nutation (= short-period,forced motion, by definition).
273  * These two dominant terms, with periods 18.6 yrs (big term) and
274  * 0.500 yrs (small term),respp., give nutation to around 1 arc sec; see
275  * p. 120 of Explan. Supp. The forced nutation amplitude
276  * is around 17 arcsec.
277  *
278  * Note the unforced motion or Chandler wobble (called ``polar motion''
279  * in Explanatory Supp) is not included here. However its amplitude is
280  * order of (and a somewhat less than) 1 arcsec; see plot on p. 270 of
281  * Explanatory Supplement to Ast. Alm.
282  *--------------------------------------------------------------------------
283  */
284  /* define variables for storing sin/cos of deltaE, eps0 etc */
285 
286  earth->delpsi = ( -0.0048e0 * LAL_PI / 180.e0 ) *
287  sin( ( 125.e0 - 0.05295e0 * daysSinceJ2000 ) * LAL_PI / 180.e0 )
288  - ( 4.e-4 * LAL_PI / 180.e0 ) *
289  sin( ( 200.9e0 + 1.97129e0 * daysSinceJ2000 ) * LAL_PI / 180.e0 );
290 
291 
292  earth->deleps = ( 0.0026e0 * LAL_PI / 180.e0 ) *
293  cos( ( 125.e0 - 0.05295e0 * daysSinceJ2000 ) * LAL_PI / 180.e0 )
294  + ( 2.e-4 * LAL_PI / 180.e0 ) *
295  cos( ( 200.9e0 + 1.97129e0 * daysSinceJ2000 ) * LAL_PI / 180.e0 );
296 
297  earth->gastRad = gmstRad + earth->delpsi * cos( eps0 );
298  /* ``equation of the equinoxes''*/
299 
300  }
301  /**********************************************************************
302  *Now calculating Einstein delay. This is just difference between
303  *TDB and TDT.
304  *We steal from TEMPO the approx 20 biggest terms in an expansion.
305  *-----------------------------------------------------------------------
306  * jedtdt is Julian date (TDT) MINUS 2451545.0 (TDT);
307  * -7300.5 = 2444244.5 (Julian date when gps clock started)
308  * - 2451545.0 TDT (approx. J2000.0);
309  * Note the 51.184 s difference between TDT and GPS
310  *-----------------------------------------------------------------------
311  */
312  {
313  REAL8 jedtdt = -7300.5e0 + ( tgps[0] + 51.184e0 + tgps[1] * 1.e-9 ) / 8.64e4;
314  REAL8 jt = jedtdt / 3.6525e5; /*converting to TEMPO expansion param
315  = Julian millenium, NOT Julian century */
316  earth->einstein = 1.e-6 * (
317  1656.674564e0 * sin( 6283.075849991e0 * jt + 6.240054195e0 ) +
318  22.417471e0 * sin( 5753.384884897e0 * jt + 4.296977442e0 ) +
319  13.839792e0 * sin( 12566.151699983e0 * jt + 6.196904410e0 ) +
320  4.770086e0 * sin( 529.690965095e0 * jt + 0.444401603e0 ) +
321  4.676740e0 * sin( 6069.776754553e0 * jt + 4.021195093e0 ) +
322  2.256707e0 * sin( 213.299095438e0 * jt + 5.543113262e0 ) +
323  1.694205e0 * sin( -3.523118349e0 * jt + 5.025132748e0 ) +
324  1.554905e0 * sin( 77713.771467920e0 * jt + 5.198467090e0 ) +
325  1.276839e0 * sin( 7860.419392439e0 * jt + 5.988822341e0 ) +
326  1.193379e0 * sin( 5223.693919802e0 * jt + 3.649823730e0 ) +
327  1.115322e0 * sin( 3930.209696220e0 * jt + 1.422745069e0 ) +
328  0.794185e0 * sin( 11506.769769794e0 * jt + 2.322313077e0 ) +
329  0.447061e0 * sin( 26.298319800e0 * jt + 3.615796498e0 ) +
330  0.435206e0 * sin( -398.149003408e0 * jt + 4.349338347e0 ) +
331  0.600309e0 * sin( 1577.343542448e0 * jt + 2.678271909e0 ) +
332  0.496817e0 * sin( 6208.294251424e0 * jt + 5.696701824e0 ) +
333  0.486306e0 * sin( 5884.926846583e0 * jt + 0.520007179e0 ) +
334  0.432392e0 * sin( 74.781598567e0 * jt + 2.435898309e0 ) +
335  0.468597e0 * sin( 6244.942814354e0 * jt + 5.866398759e0 ) +
336  0.375510e0 * sin( 5507.553238667e0 * jt + 4.103476804e0 )
337  );
338 
339  /* now adding NEXT biggest (2nd-tier) terms from Tempo */
340  earth->einstein = earth->einstein + 1.e-6 * (
341  0.243085 * sin( -775.522611324 * jt + 3.651837925 ) +
342  0.173435 * sin( 18849.227549974 * jt + 6.153743485 ) +
343  0.230685 * sin( 5856.477659115 * jt + 4.773852582 ) +
344  0.203747 * sin( 12036.460734888 * jt + 4.333987818 ) +
345  0.143935 * sin( -796.298006816 * jt + 5.957517795 ) +
346  0.159080 * sin( 10977.078804699 * jt + 1.890075226 ) +
347  0.119979 * sin( 38.133035638 * jt + 4.551585768 ) +
348  0.118971 * sin( 5486.777843175 * jt + 1.914547226 ) +
349  0.116120 * sin( 1059.381930189 * jt + 0.873504123 ) +
350  0.137927 * sin( 11790.629088659 * jt + 1.135934669 ) +
351  0.098358 * sin( 2544.314419883 * jt + 0.092793886 ) +
352  0.101868 * sin( -5573.142801634 * jt + 5.984503847 ) +
353  0.080164 * sin( 206.185548437 * jt + 2.095377709 ) +
354  0.079645 * sin( 4694.002954708 * jt + 2.949233637 ) +
355  0.062617 * sin( 20.775395492 * jt + 2.654394814 ) +
356  0.075019 * sin( 2942.463423292 * jt + 4.980931759 ) +
357  0.064397 * sin( 5746.271337896 * jt + 1.280308748 ) +
358  0.063814 * sin( 5760.498431898 * jt + 4.167901731 ) +
359  0.048042 * sin( 2146.165416475 * jt + 1.495846011 ) +
360  0.048373 * sin( 155.420399434 * jt + 2.251573730 )
361  );
362 
363 
364  /* below, I've just taken derivative of above expression for einstein,
365  then commented out terms that contribute less than around 10^{-12}
366  to tDotBary */
367 
368  earth->deinstein = 1.e-6 * (
369  1656.674564e0 * 6283.075849991e0 *
370  cos( 6283.075849991e0 * jt + 6.240054195e0 ) +
371 
372  22.417471e0 * 5753.384884897e0 *
373  cos( 5753.384884897e0 * jt + 4.296977442e0 ) +
374 
375  13.839792e0 * 12566.151699983e0 *
376  cos( 12566.151699983e0 * jt + 6.196904410e0 ) +
377 
378  /* neglect next term
379  4.770086e0*529.690965095e0*
380  cos(529.690965095e0*jt + 0.444401603e0 ) +
381  */
382  4.676740e0 * 6069.776754553e0 *
383  cos( 6069.776754553e0 * jt + 4.021195093e0 ) +
384 
385  /* neglect next 2 terms
386  2.256707e0*213.299095438e0*
387  cos(213.299095438e0*jt + 5.543113262e0 ) +
388 
389  1.694205e0*-3.523118349e0*
390  cos(-3.523118349e0*jt + 5.025132748e0 ) +
391  */
392 
393  1.554905e0 * 77713.771467920e0 *
394  cos( 77713.771467920e0 * jt + 5.198467090e0 )
395 
396  /* neglect all the rest
397  + 1.276839e0*7860.419392439e0*
398  cos(7860.419392439e0*jt + 5.988822341e0 ) +
399 
400  1.193379e0*5223.693919802e0*
401  cos(5223.693919802e0*jt + 3.649823730e0 ) +
402 
403  1.115322e0*3930.209696220e0*
404  cos(3930.209696220e0*jt + 1.422745069e0 ) +
405 
406  0.794185e0*11506.769769794e0*
407  cos(11506.769769794e0 *jt + 2.322313077e0 ) +
408 
409  0.447061e0*26.298319800e0*
410  cos(26.298319800e0*jt + 3.615796498e0 ) +
411 
412  0.435206e0*-398.149003408e0*
413  cos(-398.149003408e0*jt + 4.349338347e0 ) +
414 
415  0.600309e0*1577.343542448e0*
416  cos(1577.343542448e0*jt + 2.678271909e0 ) +
417 
418  0.496817e0*6208.294251424e0*
419  cos(6208.294251424e0*jt + 5.696701824e0 ) +
420 
421  0.486306e0*5884.926846583e0*
422  cos(5884.926846583e0*jt + 0.520007179e0 ) +
423 
424  0.432392e0*74.781598567e0*
425  cos(74.781598567e0*jt + 2.435898309e0 ) +
426 
427  0.468597e0*6244.942814354e0*
428  cos(6244.942814354e0*jt + 5.866398759e0 ) +
429 
430  0.375510e0*5507.553238667e0*
431  cos(5507.553238667e0*jt + 4.103476804e0 )
432  */
433 
434  ) / ( 8.64e4 * 3.6525e5 );
435 
436  /*Note I don't bother adding 2nd-tier terms to deinstein_tempo either */
437  }
438 
439  /********************************************************************
440  *Now calculating Earth-Sun separation vector, as needed
441  *for Shapiro delay calculation.
442  *--------------------------------------------------------------------
443  */
444  {
445  REAL8 rse2;
446  REAL8 *sunPos = edat->ephemS[ientryS].pos;
447  REAL8 *sunVel = edat->ephemS[ientryS].vel;
448  REAL8 *sunAcc = edat->ephemS[ientryS].acc;
449  REAL8 sunPosNow[3], sunVelNow[3];
450 
451  rse2 = earth->drse = 0.0;
452  for ( j = 0; j < 3; j++ ) {
453  sunPosNow[j] = sunPos[j] + sunVel[j] * tdiffS + 0.5 * sunAcc[j] * tdiff2S;
454  sunVelNow[j] = sunVel[j] + sunAcc[j] * tdiffS;
455 
456  earth->se[j] = earth->posNow[j] - sunPosNow[j];
457  earth->dse[j] = earth->velNow[j] - sunVelNow[j];
458  rse2 += earth->se[j] * earth->se[j];
459  earth->drse += earth->se[j] * earth->dse[j];
460  }
461  earth->rse = sqrt( rse2 );
462  earth->drse = earth->drse / earth->rse;
463  /* Curt: make sure rse, b, (rse +seDotN) aren't zero */
464  }
465 
466  return XLAL_SUCCESS;
467 
468 } /* XLALBarycenterEarth() */
469 
470 
471 /**
472  * \brief Computes the position and orientation of the Earth, at some arrival
473  * time, but unlike \c XLALBarycenterEarth uses look-up tables for the Einstein
474  * delay calculation.
475  *
476  * The function replicates the functionality of \c XLALBarycenterEarth, but (as
477  * in the pulsar timing software TEMPO2) will use a look-up table to compute
478  * the Einstein delay term. This function will also allow the final solar
479  * system barycentre correction to be in either Barycentric Dynamical Time
480  * (TDB), as used previously in \c XLALBarycenterEarth, or in Coordinate
481  * Barycentric Time (TCB), as is the default for TEMPO2.
482  *
483  * The function can revert to using the original \c XLALBarycenterEarth code by
484  * supplying \c TIMECORRECTION_ORIGINAL as the \c ttype input.
485  */
486 int
487 XLALBarycenterEarthNew( EarthState *earth, /**< [out] the earth's state at time tGPS */
488  const LIGOTimeGPS *tGPS, /**< [in] GPS time tgps */
489  const EphemerisData *edat, /**< [in] ephemeris-files */
490  const TimeCorrectionData *tdat, /**< [in] time correction file data */
491  TimeCorrectionType ttype /**< [in] time correction type */
492  )
493 {
494  earth->ttype = ttype; /* set TimeCorrectionType */
495 
496  /* if wanted ORIGNAL version of the code just use XLALBarycenterEarth */
497  if ( ttype == TIMECORRECTION_ORIGINAL ) {
498  return XLALBarycenterEarth( earth, tGPS, edat );
499  }
500 
501  /* start off doing the same as XLALBarycenterEarth() */
502  REAL8 tgps[2]; /*I convert from two-integer representation to
503  two REAL8s (just because I initially wrote my code for
504  REAL8s). GPS time(sec) = tgps[0] + 1.e-9*tgps[1] */
505 
506  /*int ihour; most recent hour to current time, tGPS,
507  in look-up table */
508  /*REAL8 t0,t0hr; */
509 
510  REAL8 t0e; /*time since first entry in Earth ephem. table */
511  INT4 ientryE; /*entry in look-up table closest to current time, tGPS */
512 
513  REAL8 tinitE; /*time (GPS) of first entry in Earth ephem table*/
514  REAL8 tdiffE; /*current time tGPS minus time of nearest entry
515  in Earth ephem look-up table */
516  REAL8 tdiff2E; /*tdiff2=tdiffE*tdiffE */
517  /*next entries are same as above, but for Sun table */
518  REAL8 t0s;
519  INT4 ientryS;
520  REAL8 tinitS;
521  REAL8 tdiffS;
522  REAL8 tdiff2S;
523 
524  static REAL8 scorr; /* SI second/metre correction factor */
525 
526  INT4 j; /*dummy index */
527 
528  /* check input */
529  if ( !earth || !tGPS || !edat || !edat->ephemE || !edat->ephemS || !tdat || !tdat->timeCorrs ) {
530  XLALPrintError( "%s: invalid NULL input 'earth', 'tGPS', 'edat', 'edat->ephemE', 'edat->ephemS', 'tdat' or 'tdat->timeCorrs'\n", __func__ );
532  }
533  tgps[0] = ( REAL8 )tGPS->gpsSeconds; /*convert from INT4 to REAL8 */
534  tgps[1] = ( REAL8 )tGPS->gpsNanoSeconds;
535 
536  tinitE = edat->ephemE[0].gps;
537  tinitS = edat->ephemS[0].gps;
538 
539  t0e = tgps[0] - tinitE;
540  ientryE = floor( ( t0e / edat->dtEtable ) + 0.5e0 ); /*finding Earth table entry
541  closest to arrival time*/
542  t0s = tgps[0] - tinitS;
543  ientryS = floor( ( t0s / edat->dtStable ) + 0.5e0 ); /*finding Sun table entry
544  closest to arrival time*/
545  /*Making sure tgps is within earth and sun ephemeris arrays*/
546  if ( ( ientryE < 0 ) || ( ientryE >= edat->nentriesE ) ) {
547  XLALPrintError( "%s: input GPS time %f outside of Earth ephem range [%f, %f]\n", __func__, tgps[0], tinitE, tinitE + edat->nentriesE * edat->dtEtable );
549  }
550  if ( ( ientryS < 0 ) || ( ientryS >= edat->nentriesS ) ) {
551  XLALPrintError( "%s: input GPS time %f outside of Sun ephem range [%f, %f]\n", __func__, tgps[0], tinitS, tinitS + edat->nentriesS * edat->dtStable );
553  }
554 
555  tdiffE = t0e - edat->dtEtable * ientryE + tgps[1] * 1.e-9; /*tdiff is arrival
556  time minus closest Earth table entry; tdiff can be pos. or neg. */
557  tdiff2E = tdiffE * tdiffE;
558 
559  tdiffS = t0s - edat->dtStable * ientryS + tgps[1] * 1.e-9; /*same for Sun*/
560  tdiff2S = tdiffS * tdiffS;
561 
562  /* in the TCB system the gravitational potential well of the solar system is
563  * removed, so clocks run slightly faster than the SI second by a small
564  * correction factor */
565  if ( ttype == TIMECORRECTION_TEMPO2 || ttype == TIMECORRECTION_TCB ) {
566  scorr = IFTE_K;
567  } else {
568  scorr = 1.;
569  }
570  /********************************************************************
571  *Calculate position and vel. of center of Earth.
572  *We extrapolate from a table produced using a JPL ephemeris.
573  *---------------------------------------------------------------------
574  */
575  {
576  REAL8 *pos = edat->ephemE[ientryE].pos; /*Cartesian coords of center of Earth
577  from ephem, in sec. 0=x,1=y,2=z */
578  REAL8 *vel = edat->ephemE[ientryE].vel;
579  REAL8 *acc = edat->ephemE[ientryE].acc;
580 
581  for ( j = 0; j < 3; j++ ) {
582  earth->posNow[j] = scorr * ( pos[j] + vel[j] * tdiffE + 0.5 * acc[j] * tdiff2E );
583  earth->velNow[j] = scorr * ( vel[j] + acc[j] * tdiffE );
584  }
585  }
586 
587  /********************************************************************
588  * Now calculating Earth's rotational state.
589  *---------------------------------------------------------------------
590  */
591  {
592  INT2 leapsSince2000; /*number of leap secs added to UTC calendar since
593  Jan 1, 2000 00:00:00 UTC; leap is a NEGATIVE number
594  for dates before Jan 1, 2000. */
595 
596  REAL8 tu0JC; /*time elapsed on UT1 clock (in Julian centuries)
597  between Jan 1.5 2000 (= J2000 epoch)
598  and midnight before gps[0,j] */
599 
600  REAL8 tuJC; /*time elapsed on UT1 clock (in Julian centuries)
601  between Jan 1.5 2000 (= J2000 epoch)
602  and the present time (tGPS) */
603 
604  INT4 tuInt; /*number of full seconds (integer) on elapsed
605  on UT1 clock from Jan 1, 2000 00:00:00 UTC to present*/
606  REAL8 dtu; /*see comments below*/
607 
608  REAL8 gmst; /*Greenwich mean sidereal time at present (tGPS), in sec */
609  REAL8 gmst0; /*Greenwich mean sidereal time at prev. midnight, in sec */
610  REAL8 gmstRad; /*gmst, but in radians*/
611 
612  INT4 ut1secSince1Jan2000, fullUt1days;
613  REAL8 daysSinceJ2000;
614  REAL8 eps0 = OBLQ; /*obliquity of ecliptic at JD 245145.0*/
615 
616  leapsSince2000 = 0; /*right # for Jan. 1, 2000 */
617  leapsSince2000 = XLALGPSLeapSeconds( tGPS->gpsSeconds ) - 13;
618  {
619  INT4 err = xlalErrno;
620  if ( err != XLAL_SUCCESS ) {
621  XLALPrintError( "%s: XLALGPSLeapSeconds (%d) failed.\n", __func__, tGPS->gpsSeconds );
623  }
624  }
625 
626  tuInt = tGPS->gpsSeconds - 630720013; /*first subtract off value
627  of gps clock at Jan 1, 2000 00:00:00 UTC */
628 
629  ut1secSince1Jan2000 = tuInt - leapsSince2000; /*next subtract
630  off # leap secs added to UTC calendar since Jan 1, 2000 00:00:00 UTC */
631  tuJC = ( ut1secSince1Jan2000 + tgps[1] * 1.e-9 - 43200 ) / ( 8.64e4 * 36525 );
632  /*UT1 time elapsed, in Julian centuries, since Jan 1.5 2000
633  (= J2000 epoch) and pulse arrival time*/
634 
635  fullUt1days = floor( ut1secSince1Jan2000 / 8.64e4 );/*full days on ut1 clock
636  since Jan 1, 2000 00:00:00 UTC */
637 
638  tu0JC = ( fullUt1days - 0.5e0 ) / 36525.0; /* UT1 time elapsed,
639  in Julian centuries between Jan 1.5 2000 (= J2000 epoch)
640  and midnight before gps[0,j] */
641 
642  dtu = tuJC - tu0JC; /*time, in Jul. centuries, between pulse arrival time and previous midnight (UT1) */
643 
644  daysSinceJ2000 = ( tuInt - 43200. ) / 8.64e4; /*days(not int) on GPS
645  (or TAI,etc.) clock since J2000 */
646 
647  /*----------------------------------------------------------------------
648  * in below formula for gmst0 & gmst, on rhs we SHOULD use time elapsed
649  * in UT1, but instead we insert elapsed in UTC. This will lead to
650  * errors in tdb of order 1 microsec.
651  *----------------------------------------------------------------------
652  */
653 
654  gmst0 = 24110.54841e0 + tu0JC * ( 8640184.812866e0 + tu0JC * ( 0.093104e0 - tu0JC * 6.2e-6 ) );
655  /*formula for Greenwich mean sidereal time
656  on p.50 of Explanatory Supp. to Ast Alm. ...
657  gmst unit is sec, where 2pi rad = 24*60*60sec */
658 
659  /*-----------------------------------------------------------------------
660  * Explan of tu0JC*8640184.812866e0 term: when tu0JC0=0.01 Julian centuries
661  * (= 1 year), Earth has spun an extra 86401.84 sec (approx one revolution)
662  * with respect to the stars.
663  *
664  * Note: this way of organizing calc of gmst was stolen from TEMPO;
665  * see subroutine lmst (= local mean sidereal time) .
666  *------------------------------------------------------------------------
667  */
668 
669  gmst = gmst0 + dtu * ( 8.64e4 * 36525. + 8640184.812866e0
670  + 0.093104e0 * ( tuJC + tu0JC )
671  - 6.2e-6 * ( tuJC * tuJC + tuJC * tu0JC + tu0JC * tu0JC ) );
672 
673  gmstRad = gmst * LAL_PI / 43200.;
674 
675  earth->gmstRad = gmstRad;
676 
677  /*------------------------------------------------------------------------
678  * Now calculating 3 terms, describing lunisolar precession;
679  * see Eqs. 3.212 on pp. 104-5 in Explanatory Supp.
680  *-------------------------------------------------------------------------
681  */
682 
683  earth->tzeA = tuJC * ( 2306.2181e0 + ( 0.30188e0 + 0.017998e0 * tuJC ) * tuJC )
684  * LAL_PI / 6.48e5;
685 
686  earth->zA = tuJC * ( 2306.2181e0 + ( 1.09468e0 + 0.018203e0 * tuJC ) * tuJC )
687  * LAL_PI / 6.48e5;
688 
689  earth->thetaA = tuJC * ( 2004.3109e0 - ( 0.42665e0 + 0.041833 * tuJC ) * tuJC )
690  * LAL_PI / 6.48e5;
691 
692  /*--------------------------------------------------------------------------
693  * Now adding approx nutation (= short-period,forced motion, by definition).
694  * These two dominant terms, with periods 18.6 yrs (big term) and
695  * 0.500 yrs (small term),respp., give nutation to around 1 arc sec; see
696  * p. 120 of Explan. Supp. The forced nutation amplitude
697  * is around 17 arcsec.
698  *
699  * Note the unforced motion or Chandler wobble (called ``polar motion''
700  * in Explanatory Supp) is not included here. However its amplitude is
701  * order of (and a somewhat less than) 1 arcsec; see plot on p. 270 of
702  * Explanatory Supplement to Ast. Alm.
703  *--------------------------------------------------------------------------
704  */
705  /* define variables for storing sin/cos of deltaE, eps0 etc */
706  earth->delpsi = ( -0.0048e0 * LAL_PI / 180.e0 ) *
707  sin( ( 125.e0 - 0.05295e0 * daysSinceJ2000 ) * LAL_PI / 180.e0 )
708  - ( 4.e-4 * LAL_PI / 180.e0 ) *
709  sin( ( 200.9e0 + 1.97129e0 * daysSinceJ2000 ) * LAL_PI / 180.e0 );
710 
711  earth->deleps = ( 0.0026e0 * LAL_PI / 180.e0 ) *
712  cos( ( 125.e0 - 0.05295e0 * daysSinceJ2000 ) * LAL_PI / 180.e0 )
713  + ( 2.e-4 * LAL_PI / 180.e0 ) *
714  cos( ( 200.9e0 + 1.97129e0 * daysSinceJ2000 ) * LAL_PI / 180.e0 );
715 
716  earth->gastRad = gmstRad + earth->delpsi * cos( eps0 );
717  /* ``equation of the equinoxes''*/
718  }
719  /**********************************************************************
720  * Now calculating Einstein delay using the look-up table and linearly
721  * interpolating between points. Depending on the ephemeris type this is
722  * either the difference between TDB and TDT, or TCB and TDT. The
723  * TCB calculation includes a linear drift term correcting the SSB time
724  * to be outside the solar systems gravitational potential. These
725  * calculations are taken from the TEMPO2 tt2tdb.C file.
726  *
727  * Note the 51.184 s difference between TDT and GPS
728  *-----------------------------------------------------------------------
729  */
730  {
731  /* get deltaT from the look-up table */
732  INT4 cidx = floor( ( ( tgps[0] + tgps[1] * 1.e-9 ) - tdat->timeCorrStart ) / tdat->dtTtable );
733 
734  if ( cidx < 0 || cidx > ( INT4 )tdat->nentriesT - 2 ) {
735  XLALPrintError( "%s: input GPS time %f outside of time ephem range\n", __func__, tgps[0] );
737  }
738 
739  REAL8 dtidx = ( tgps[0] + tgps[1] * 1.e-9 ) - ( tdat->timeCorrStart + ( REAL8 )cidx * tdat->dtTtable );
740  REAL8 grad = ( tdat->timeCorrs[cidx + 1] - tdat->timeCorrs[cidx] ) / tdat->dtTtable;
741 
742  REAL8 deltaT = tdat->timeCorrs[cidx] + grad * dtidx;
743 
744  REAL8 correctionTT_Teph;
745 
746  correctionTT_Teph = IFTE_TEPH0 + deltaT / ( 1.0 - IFTE_LC );
747  /* the observatory term (obsTerm) correction from TEMPO2's tt2tdb.C code
748  is added in XLALBarycenter */
749  if ( ttype == TIMECORRECTION_TEMPO || ttype == TIMECORRECTION_TDB ) { /* conversion for TDT to TDB using lookup table */
750  /* add correction offset as in TEMPO2 tt2tdb.C to
751  * account for its readdition in correctionTT_Teph */
752  correctionTT_Teph -= IFTE_TEPH0 / ( 1.0 - IFTE_LC );
753  earth->einstein = correctionTT_Teph;
754  earth->deinstein = 0.;
755  }
756  /* conversion for TDT to TCB using lookup table */
757  else if ( ttype == TIMECORRECTION_TEMPO2 || ttype == TIMECORRECTION_TCB ) {
758  /* GPS time in MJD */
759  REAL8 mjdtt = 44244. + ( ( tgps[0] + tgps[1] * 1.e-9 ) + 51.184 ) / 86400.;
760 
761  earth->einstein = IFTE_KM1 * ( mjdtt - IFTE_MJD0 ) * 86400.0 /* linear drift term */
762  + IFTE_K * ( correctionTT_Teph - ( long double )IFTE_TEPH0 );
763  earth->deinstein = IFTE_KM1; /* account for the drift in the derivative */
764  }
765 
766  /* now get the time derivative using Curt's method: NOTE: this really should be
767  checked as the differences may not be negligble */
768  REAL8 jedtdt = -7300.5e0 + ( tgps[0] + 51.184e0 + tgps[1] * 1.e-9 ) / 8.64e4;
769  REAL8 jt = jedtdt / 3.6525e5; /*converting to TEMPO expansion param
770  = Julian millenium, NOT Julian century */
771 
772  /* below, I've just taken derivative of above expression for einstein,
773  then commented out terms that contribute less than around 10^{-12}
774  to tDotBary */
775  earth->deinstein += 1.e-6 * (
776  1656.674564e0 * 6283.075849991e0 * cos( 6283.075849991e0 * jt + 6.240054195e0 ) +
777  22.417471e0 * 5753.384884897e0 * cos( 5753.384884897e0 * jt + 4.296977442e0 ) +
778  13.839792e0 * 12566.151699983e0 * cos( 12566.151699983e0 * jt + 6.196904410e0 ) +
779  4.676740e0 * 6069.776754553e0 * cos( 6069.776754553e0 * jt + 4.021195093e0 ) +
780  1.554905e0 * 77713.771467920e0 * cos( 77713.771467920e0 * jt + 5.198467090e0 )
781  ) / ( 8.64e4 * 3.6525e5 );
782  }
783 
784  /********************************************************************
785  *Now calculating Earth-Sun separation vector, as needed
786  *for Shapiro delay calculation.
787  *--------------------------------------------------------------------
788  */
789  {
790  REAL8 rse2;
791  REAL8 *sunPos = edat->ephemS[ientryS].pos;
792  REAL8 *sunVel = edat->ephemS[ientryS].vel;
793  REAL8 *sunAcc = edat->ephemS[ientryS].acc;
794  REAL8 sunPosNow[3], sunVelNow[3];
795 
796  rse2 = earth->drse = 0.0;
797  for ( j = 0; j < 3; j++ ) {
798  sunPosNow[j] = scorr * ( sunPos[j] + sunVel[j] * tdiffS + 0.5 * sunAcc[j] * tdiff2S );
799  sunVelNow[j] = scorr * ( sunVel[j] + sunAcc[j] * tdiffS );
800 
801  earth->se[j] = earth->posNow[j] - sunPosNow[j];
802  earth->dse[j] = earth->velNow[j] - sunVelNow[j];
803  rse2 += earth->se[j] * earth->se[j];
804  earth->drse += earth->se[j] * earth->dse[j];
805  }
806  earth->rse = sqrt( rse2 );
807  earth->drse = earth->drse / earth->rse;
808  /* Curt: make sure rse, b, (rse +seDotN) aren't zero */
809  }
810 
811  return XLAL_SUCCESS;
812 
813 } /* XLALBarycenterEarthNew() */
814 
815 
816 /**
817  * \author Curt Cutler
818  * \brief Transforms from detector arrival time \f$ t_a \f$ in GPS (as specified in the
819  * LIGOTimeGPS structure) to pulse emission time \f$ t_e \f$ , in TDB.
820  *
821  * Actually, the returned \f$ t_e \f$ is
822  * the emission time plus the constant light-travel-time from
823  * source to SSB.) The inputs to XLALBarycenter(), through
824  * the BarycenterInput structure, are the source location,
825  * detector site identifier, and GPS arrival time.
826  * The function returns the emission time \f$ t_e(t_a) \f$ , the
827  * derivative \f$ d t_e/d t_a \f$ , and the difference
828  * \f$ t_e(t_a) - t_a \f$ through the EmissionTime structure.
829  * The emission time \f$ t_e(t_a) \f$ is returned in the LIGOTimeGPS format,
830  * while the other two quantities are REAL8's.
831  */
832 int
833 XLALBarycenter( EmissionTime *emit, /**< [out] emission-time information */
834  const BarycenterInput *baryinput, /**< [in] info about detector and source-location */
835  const EarthState *earth ) /**< [in] earth-state (from XLALBarycenterEarth()) */
836 {
837  REAL8 longitude, latitude, rd; /*geocentric (not geodetic!!) longitude
838  and latitude of detector vertex, and
839  dist. rd from center of Earth (sec). */
840  REAL8 OMEGA = 7.29211510e-5; /*ang. vel. of Earth (rad/sec)*/
841 
842  REAL8 alpha, delta; /* RA and DEC (radians) in
843  ICRS realization of J2000 coords.*/
844 
845  REAL8 sinTheta; /* sin(theta) = sin(pi/2 - delta) */
846 
847  REAL8 tgps[2]; /*I convert from two-integer representation to
848  two REAL8s (just because I initially wrote my code for
849  REAL8s). GPS time(sec) = tgps[0] + 1.e-9*tgps[1] */
850 
851  REAL8 roemer, droemer; /*Roemer delay and its time derivative*/
852  REAL8 erot, derot; /*delay from center-of-Earth to detector (sec),
853  and its time deriv */
854  REAL8 shapiro, dshapiro; /*Shapiro delay due to Sun, and its time deriv. */
855  REAL8 finiteDistCorr, dfiniteDistCorr; /*correction to Roemer delay due
856  to finite dist D to source;
857  important for D < 100pc */
858  REAL8 s[3]; /*unit vector pointing at source, in J2000 Cartesian coords */
859  INT4 j; /*dummy index */
860 
861  /* check input */
862  if ( !emit || !baryinput || !earth ) {
863  XLALPrintError( "%s: invalid NULL input 'baryinput, 'emit' or 'earth'\n", __func__ );
865  }
866 
867  tgps[0] = ( REAL8 )baryinput->tgps.gpsSeconds; /*convert from INT4 to REAL8 */
868  tgps[1] = ( REAL8 )baryinput->tgps.gpsNanoSeconds;
869 
870  alpha = baryinput->alpha;
871  delta = baryinput->delta;
872 
873  /* check that alpha and delta are in reasonable range */
874  if ( ( fabs( alpha ) > LAL_TWOPI ) || ( fabs( delta ) > LAL_PI_2 ) ) {
875  XLALPrintError( "%s: alpha = %f outside of [-2pi,2pi] or delta = %f outside of [-pi/2,pi/2]\n", __func__, alpha, delta );
877  }
878 
879  sinTheta = sin( LAL_PI / 2.0 - delta );
880  s[2] = cos( LAL_PI / 2.0 - delta ); /* s is vector that points towards source */
881  s[1] = sinTheta * sin( alpha ); /* in Cartesian coords based on J2000 */
882  s[0] = sinTheta * cos( alpha ); /* 0=x,1=y,2=z */
883 
884  rd = sqrt( baryinput->site.location[0] * baryinput->site.location[0]
885  + baryinput->site.location[1] * baryinput->site.location[1]
886  + baryinput->site.location[2] * baryinput->site.location[2] );
887  if ( rd == 0.0 ) {
888  latitude = LAL_PI_2;
889  } else {
890  latitude = LAL_PI_2 - acos( baryinput->site.location[2] / rd );
891  }
892  longitude = atan2( baryinput->site.location[1], baryinput->site.location[0] );
893 
894  /********************************************************************
895  *Calucate Roemer delay for detector at center of Earth.
896  *We extrapolate from a table produced using JPL DE405 ephemeris.
897  *---------------------------------------------------------------------
898  */
899  {
900  roemer = droemer = 0.0;
901  for ( j = 0; j < 3; j++ ) {
902  roemer += s[j] * earth->posNow[j];
903  droemer += s[j] * earth->velNow[j];
904  }
905  emit->roemer = roemer;
906  emit->droemer = droemer;
907  }
908 
909  /* get the observatory term (if not using the original XLALBarycenterEarth function) */
910  REAL8 obsTerm = 0; /* observatory term correction from TEMPO2 tt2tdb.C */
911  if ( earth->ttype != TIMECORRECTION_ORIGINAL ) {
912  REAL8 obsEarth[3];
913  observatoryEarth( obsEarth, baryinput->site, &baryinput->tgps, earth->gmstRad, earth->delpsi, earth->deleps );
914 
915  for ( j = 0; j < 3; j++ ) {
916  obsTerm += obsEarth[j] * earth->velNow[j];
917  }
918 
919  obsTerm /= ( 1.0 - IFTE_LC ) * ( REAL8 )IFTE_K;
920  }
921 
922  /********************************************************************
923  * Now including Earth's rotation
924  *---------------------------------------------------------------------
925  */
926  {
927 
928  REAL8 eps0 = OBLQ;/*obliquity of ecliptic at JD 245145.0,
929  in radians. NOT! to be confused with
930  LAL_EPSILON0_SI = permittivity of free
931  space; value from Explan. Supp.
932  to Astronom. Almanac */
933  /* REAL8 eps0= (23.e0 + 26.e0/60 + 21.448e0/3.6e3)*LAL_PI/180; */
934 
935  REAL8 NdotD;
936  REAL8 cosDeltaSinAlphaMinusZA, cosDeltaCosAlphaMinusZA, sinDelta;
937  /* above used in calculating effect of luni-solar precession*/
938 
939  REAL8 delXNut, delYNut, delZNut, NdotDNut; /* used in calculating effect
940  of forced nutation */
941 
942  cosDeltaSinAlphaMinusZA = sin( alpha + earth->tzeA ) * cos( delta );
943 
944  cosDeltaCosAlphaMinusZA = cos( alpha + earth->tzeA ) * cos( earth->thetaA )
945  * cos( delta ) - sin( earth->thetaA ) * sin( delta );
946 
947  sinDelta = cos( alpha + earth->tzeA ) * sin( earth->thetaA ) * cos( delta )
948  + cos( earth->thetaA ) * sin( delta );
949 
950  /*now taking NdotD, including lunisolar precession, using
951  Eqs. 3.212-2 of Explan. Supp.
952  Basic idea for incorporating luni-solar precession
953  is to change the (alpha,delta) of source to compensate for
954  Earth's time-changing spin axis.
955  */
956 
957  NdotD = sin( latitude ) * sinDelta + cos( latitude ) * (
958  cos( earth->gastRad + longitude - earth->zA ) * cosDeltaCosAlphaMinusZA
959  + sin( earth->gastRad + longitude - earth->zA ) * cosDeltaSinAlphaMinusZA );
960 
961  erot = rd * NdotD;
962 
963  derot = OMEGA * rd * cos( latitude ) * (
964  - sin( earth->gastRad + longitude - earth->zA ) * cosDeltaCosAlphaMinusZA
965  + cos( earth->gastRad + longitude - earth->zA ) * cosDeltaSinAlphaMinusZA );
966 
967 
968  /*--------------------------------------------------------------------------
969  * Now adding approx nutation (= short-period,forced motion, by definition).
970  * These two dominant terms, with periods 18.6 yrs (big term) and
971  * 0.500 yrs (small term),resp., give nutation to around 1 arc sec; see
972  * p. 120 of Explan. Supp. The forced nutation amplitude
973  * is around 17 arcsec.
974  *
975  * Note the unforced motion or Chandler wobble (called ``polar motion''
976  * in Explanatory Supp) is not included here. However its amplitude is
977  * order of (and a somewhat less than) 1 arcsec; see plot on p. 270 of
978  * Explanatory Supplement to Ast. Alm.
979  *
980  *Below correction for nutation from Eq.3.225-2 of Explan. Supp.
981  *Basic idea is to change the (alpha,delta) of source to
982  *compensate for Earth's time-changing spin axis.
983  *--------------------------------------------------------------------------
984  */
985 
986  delXNut = -( earth->delpsi ) * ( cos( delta ) * sin( alpha ) * cos( eps0 )
987  + sin( delta ) * sin( eps0 ) );
988 
989  delYNut = cos( delta ) * cos( alpha ) * cos( eps0 ) * ( earth->delpsi )
990  - sin( delta ) * ( earth->deleps );
991 
992  delZNut = cos( delta ) * cos( alpha ) * sin( eps0 ) * ( earth->delpsi )
993  + cos( delta ) * sin( alpha ) * ( earth->deleps );
994 
995 
996  NdotDNut = sin( latitude ) * delZNut
997  + cos( latitude ) * cos( earth->gastRad + longitude ) * delXNut
998  + cos( latitude ) * sin( earth->gastRad + longitude ) * delYNut;
999 
1000  erot = erot + rd * NdotDNut;
1001 
1002  derot = derot + OMEGA * rd * (
1003  -cos( latitude ) * sin( earth->gastRad + longitude ) * delXNut
1004  + cos( latitude ) * cos( earth->gastRad + longitude ) * delYNut );
1005 
1006  emit->erot = erot;
1007  emit->derot = derot;
1008  /* Note erot has a periodic piece (P=one day) AND a constant piece,
1009  since z-component (parallel to North pole) of vector from
1010  Earth-center to detector is constant */
1011 
1012  }
1013 
1014  /********************************************************************
1015  *Now adding Shapiro delay. Note according to J. Taylor review article
1016  *on pulsar timing, max value of Shapiro delay (when rays just graze sun)
1017  *is 120 microsec.
1018  *
1019  *Here we calculate Shapiro delay
1020  *for a detector at the center of the Earth.
1021  *Causes errors of order 10^{-4}sec * 4 * 10^{-5} = 4*10^{-9} sec
1022  *--------------------------------------------------------------------
1023  */
1024  {
1025  REAL8 seDotN, dseDotN, b, db;
1026  REAL8 rsun = 2.322e0; /*radius of sun in sec */
1027  seDotN = earth->se[2] * sin( delta ) + ( earth->se[0] * cos( alpha )
1028  + earth->se[1] * sin( alpha ) ) * cos( delta );
1029  dseDotN = earth->dse[2] * sin( delta ) + ( earth->dse[0] * cos( alpha )
1030  + earth->dse[1] * sin( alpha ) ) * cos( delta );
1031 
1032  b = sqrt( earth->rse * earth->rse - seDotN * seDotN );
1033  db = ( earth->rse * earth->drse - seDotN * dseDotN ) / b;
1034 
1035 
1036  if ( ( b < rsun ) && ( seDotN < 0.e0 ) ) { /*if gw travels thru interior of Sun*/
1037  shapiro = 9.852e-6 * log( ( LAL_AU_SI / LAL_C_SI ) /
1038  ( seDotN + sqrt( rsun * rsun + seDotN * seDotN ) ) )
1039  + 19.704e-6 * ( 1.e0 - b / rsun );
1040  dshapiro = - 19.704e-6 * db / rsun;
1041  } else { /*else the usual expression*/
1042  shapiro = 9.852e-6 * log( ( LAL_AU_SI / LAL_C_SI ) / ( earth->rse + seDotN ) );
1043  dshapiro = -9.852e-6 * ( earth->drse + dseDotN ) / ( earth->rse + seDotN );
1044  }
1045 
1046  emit->shapiro = shapiro;
1047  emit->dshapiro = dshapiro;
1048  }
1049  /********************************************************************
1050  *Now correcting Roemer delay for finite distance to source.
1051  *Timing corrections are order 10 microsec
1052  *for sources closer than about 100 pc = 10^10 sec.
1053  *--------------------------------------------------------------------
1054  */
1055  {
1056  REAL8 r2 = 0.e0; /*squared dist from SSB to center of earth, in sec^2 */
1057  REAL8 dr2 = 0.e0; /*time deriv of r2 */
1058  if ( baryinput->dInv > 1.0e-11 ) { /*implement if corr. > 1 microsec*/
1059  for ( j = 0; j < 3; j++ ) {
1060  r2 += earth->posNow[j] * earth->posNow[j];
1061  dr2 += 2.e0 * earth->posNow[j] * earth->velNow[j];
1062  }
1063  finiteDistCorr = -0.5e0 * ( r2 - roemer * roemer ) * baryinput->dInv;
1064  dfiniteDistCorr = -( 0.5e0 * dr2 - roemer * droemer ) * baryinput->dInv;
1065  } else {
1066  finiteDistCorr = 0.e0;
1067  dfiniteDistCorr = 0.e0;
1068  }
1069  }
1070  /*-----------------------------------------------------------------------
1071  *Now adding it all up.
1072  *emit.te is pulse emission time in TDB coords
1073  *(up to a constant roughly equal to ligh travel time from source to SSB).
1074  *emit->deltaT = emit.te - tgps.
1075  *-----------------------------------------------------------------------
1076  */
1077  {
1078 
1079  INT4 deltaTint; /* floor of deltaT */
1080 
1081  emit->deltaT = roemer + erot + obsTerm + earth->einstein - shapiro + finiteDistCorr;
1082 
1083  emit->tDot = 1.e0 + droemer + derot + earth->deinstein - dshapiro + dfiniteDistCorr;
1084 
1085  deltaTint = ( INT4 )floor( emit->deltaT );
1086 
1087  if ( ( 1.e-9 * tgps[1] + emit->deltaT - deltaTint ) >= 1.e0 ) {
1088  emit->te.gpsSeconds = baryinput->tgps.gpsSeconds + deltaTint + 1;
1089  emit->te.gpsNanoSeconds = ( INT4 )floor( 1.e9 * ( tgps[1] * 1.e-9
1090  + emit->deltaT - deltaTint - 1.e0 ) );
1091  } else {
1092  emit->te.gpsSeconds = baryinput->tgps.gpsSeconds + deltaTint;
1093  emit->te.gpsNanoSeconds = ( INT4 )floor( 1.e9 * ( tgps[1] * 1.e-9
1094  + emit->deltaT - deltaTint ) );
1095  }
1096 
1097  {
1098  for ( j = 0; j < 3; j++ ) {
1099  emit->rDetector[j] = earth->posNow[j];
1100  emit->vDetector[j] = earth->velNow[j];
1101  }
1102  /*Now adding Earth's rotation to rDetector and
1103  vDetector, but NOT yet including effects of
1104  lunisolar prec. or nutation (though DO use gast instead of gmst)
1105  For next 10 years, will give rDetector to 10 microsec and
1106  v/c to 10^-9 */
1107  emit->rDetector[0] += rd * cos( latitude ) * cos( longitude + earth->gastRad );
1108  emit->vDetector[0] += -OMEGA * rd * cos( latitude ) *
1109  sin( longitude + earth->gastRad );
1110  emit->rDetector[1] += rd * cos( latitude ) * sin( longitude + earth->gastRad );
1111  emit->vDetector[1] += OMEGA * rd * cos( latitude ) *
1112  cos( longitude + earth->gastRad );
1113  emit->rDetector[2] += rd * sin( latitude );
1114  /*no change to emit->vDetector[2] = component along spin axis,
1115  if ignore prec. and nutation */
1116  }
1117 
1118  }
1119 
1120  return XLAL_SUCCESS;
1121 
1122 } /* XLALBarycenter() */
1123 
1124 /**
1125  * \author Curt Cutler, Miroslav Shaltev, R Prix
1126  * \brief Speed optimized version of XLALBarycenter(),
1127  * should be fully equivalent except for the additional buffer argument.
1128  * The 'buffer' is used to keep sky-specific and detector-specific values that can can potentially be re-used
1129  * across subsequent calls to this function.
1130  *
1131  * NOTE: The 'buffer' argument is a pointer to a buffer-pointer, which is allowed to be buffer==NULL (=> no buffering),
1132  * otherwise a given non-NULL (*buffer) is re-used, or if (*buffer==NULL) we create a new one and return in (*buffer).
1133  *
1134  */
1135 int
1136 XLALBarycenterOpt( EmissionTime *emit, /**< [out] emission-time information */
1137  const BarycenterInput *baryinput, /**< [in] info about detector and source-location */
1138  const EarthState *earth, /**< [in] earth-state (from XLALBarycenterEarth()) */
1139  BarycenterBuffer **buffer /**< [in/out] internal buffer for speed optimization */
1140  )
1141 {
1142  /* ---------- check input sanity ---------- */
1143  XLAL_CHECK( emit != NULL, XLAL_EINVAL, "Invalid input: emit == NULL" );
1144  XLAL_CHECK( baryinput != NULL, XLAL_EINVAL, "Invalid input: baryinput == NULL" );
1145  XLAL_CHECK( earth != NULL, XLAL_EINVAL, "Invalid input: earth == NULL" );
1146  XLAL_CHECK( buffer != NULL, XLAL_EINVAL, "Invalid input: buffer == NULL" );
1147 
1148  // physical constants used by Curt (slightly different from LAL's Constants, but kept for binary-equivalence with XLALBarycenter()
1149  const REAL8 OMEGA = 7.29211510e-5; /* ang. vel. of Earth (rad/sec)*/
1150  // REAL8 eps0 = 0.40909280422232891; /* obliquity of ecliptic at JD 245145.0, in radians. Value from Explan. Supp. to Astronom. Almanac */
1151  const REAL8 sinEps0 = 0.397777155931914; // sin ( eps0 );
1152  const REAL8 cosEps0 = 0.917482062069182; // cos ( eps0 );
1153 
1154  REAL8 tgps[2];
1155  tgps[0] = baryinput->tgps.gpsSeconds;
1156  tgps[1] = baryinput->tgps.gpsNanoSeconds;
1157 
1158  // ---------- sky-position dependent quantities: compute or re-use from buffer is applicable
1159  REAL8 alpha, delta; /* RA and DEC (radians) in ICRS realization of J2000 coords.*/
1160  alpha = baryinput->alpha;
1161  delta = baryinput->delta;
1162 
1163  REAL8 sinAlpha, cosAlpha, sinDelta, cosDelta;
1164  REAL8 n[3]; /*unit vector pointing from SSB to the source, in J2000 Cartesian coords, 0=x,1=y,2=z */
1165 
1166  // ---------- handle buffering of recurring computed quantities
1167  // 3 possible scenarios:
1168  // i) caller gave as an initialized buffer: we use that one
1169  // ii) caller gave as a pointer to a NULL-initialized buffer-pointer: allocate buffer, initialize and pass back to caller
1170  // iii) caller gave as a NULL pointer: use buffer internally, but destroy at the end of this function
1171  BarycenterBuffer *myBuffer = NULL;
1172  if ( ( buffer ) && ( *buffer ) ) { // caller gave as an allocated buffer
1173  myBuffer = ( *buffer );
1174  } else { // we need to create a buffer
1175  XLAL_CHECK( ( myBuffer = XLALCalloc( 1, sizeof( *myBuffer ) ) ) != NULL, XLAL_ENOMEM, "Failed to XLALCalloc(1,sizeof(*myBuffer))\n" );
1176  }
1177 
1178  // now we're (basically) guaranteed to have a valid buffer in 'myBuffer'
1179 
1180  // use buffered sky-quantities if same sky-position as stored in buffer
1181  if ( myBuffer->active && ( alpha == myBuffer->alpha ) && ( delta == myBuffer->delta ) ) {
1182  sinDelta = myBuffer->fixed_sky.sinDelta;
1183  cosDelta = myBuffer->fixed_sky.cosDelta;
1184  sinAlpha = myBuffer->fixed_sky.sinAlpha;
1185  cosAlpha = myBuffer->fixed_sky.cosAlpha;
1186  n[0] = myBuffer->fixed_sky.n[0];
1187  n[1] = myBuffer->fixed_sky.n[1];
1188  n[2] = myBuffer->fixed_sky.n[2];
1189  } else { // not buffered, recompute sky-dependent quantities
1190  /* check that alpha and delta are in reasonable range */
1191  XLAL_CHECK( fabs( alpha ) <= LAL_TWOPI, XLAL_EDOM, "alpha = %f outside of allowed range [-2pi,2pi]\n", alpha );
1192  XLAL_CHECK( fabs( delta ) <= LAL_PI_2, XLAL_EDOM, "delta = %f outside of allowed range [-pi/2,pi/2]\n", delta );
1193 
1194  sinDelta = cos( LAL_PI / 2.0 - delta ); // this weird way of computing it is required to stay binary identical to Curt's function
1195  cosDelta = sin( LAL_PI / 2.0 - delta );
1196  sinAlpha = sin( alpha );
1197  cosAlpha = cos( alpha );
1198 
1199  n[0] = cosDelta * cosAlpha;
1200  n[1] = cosDelta * sinAlpha;
1201  n[2] = sinDelta;
1202 
1203  // ... and store them in the myBuffer
1204  myBuffer->alpha = alpha;
1205  myBuffer->delta = delta;
1206  myBuffer->fixed_sky.sinDelta = sinDelta;
1207  myBuffer->fixed_sky.cosDelta = cosDelta;
1208  myBuffer->fixed_sky.sinAlpha = sinAlpha;
1209  myBuffer->fixed_sky.cosAlpha = cosAlpha;
1210  myBuffer->fixed_sky.n[0] = n[0];
1211  myBuffer->fixed_sky.n[1] = n[1];
1212  myBuffer->fixed_sky.n[2] = n[2];
1213  myBuffer->active = 1;
1214  } // if not re-using sky-buffered quantities
1215 
1216  // ---------- detector site-position dependent quantities: compute or re-use from buffer is applicable
1217  REAL8 rd; /* distance 'rd' of detector from center of Earth, in light seconds */
1218  REAL8 longitude, latitude; /* geocentric (not geodetic!!) longitude and latitude of detector vertex */
1219  REAL8 sinLat, cosLat;
1220  REAL8 rd_sinLat, rd_cosLat; // shortcuts for 'rd * sin(latitude)' and 'rd * cos(latitude)' respectively
1221 
1222  // use buffered site-quantities if same site as stored in myBuffer
1223  if ( myBuffer->active && ( memcmp( &baryinput->site, &myBuffer->site, sizeof( myBuffer->site ) ) == 0 ) ) {
1224  rd = myBuffer->fixed_site.rd;
1225  longitude = myBuffer->fixed_site.longitude;
1226  latitude = myBuffer->fixed_site.latitude;
1227  sinLat = myBuffer->fixed_site.sinLat;
1228  cosLat = myBuffer->fixed_site.cosLat;
1229  rd_sinLat = myBuffer->fixed_site.rd_sinLat;
1230  rd_cosLat = myBuffer->fixed_site.rd_cosLat;
1231  } else {
1232  rd = sqrt( + baryinput->site.location[0] * baryinput->site.location[0]
1233  + baryinput->site.location[1] * baryinput->site.location[1]
1234  + baryinput->site.location[2] * baryinput->site.location[2] );
1235 
1236  longitude = atan2( baryinput->site.location[1], baryinput->site.location[0] );
1237  if ( rd == 0.0 ) {
1238  latitude = LAL_PI_2; // avoid division by 0, for detector at center of earth
1239  } else {
1240  latitude = LAL_PI_2 - acos( baryinput->site.location[2] / rd );
1241  }
1242 
1243  sinLat = sin( latitude );
1244  cosLat = cos( latitude );
1245  rd_sinLat = rd * sinLat;
1246  rd_cosLat = rd * cosLat;
1247 
1248  // ... and store them in the myBuffer
1249  memcpy( &myBuffer->site, &baryinput->site, sizeof( myBuffer->site ) );
1250  myBuffer->fixed_site.rd = rd;
1251  myBuffer->fixed_site.longitude = longitude;
1252  myBuffer->fixed_site.latitude = latitude;
1253  myBuffer->fixed_site.sinLat = sinLat;
1254  myBuffer->fixed_site.cosLat = cosLat;
1255  myBuffer->fixed_site.rd_sinLat = rd_sinLat;
1256  myBuffer->fixed_site.rd_cosLat = rd_cosLat;
1257  myBuffer->active = 1;
1258  } // if not re-using site-buffered quantities
1259 
1260  /*---------------------------------------------------------------------
1261  * Calucate Roemer delay for detector at center of Earth.
1262  * We extrapolate from a table produced using JPL DE405 ephemeris.
1263  *---------------------------------------------------------------------
1264  */
1265  /*Roemer delay and its time derivative*/
1266  emit->roemer = 0;
1267  emit->droemer = 0;
1268  for ( UINT4 j = 0; j < 3; j++ ) {
1269  emit->roemer += n[j] * earth->posNow[j];
1270  emit->droemer += n[j] * earth->velNow[j];
1271  }
1272 
1273  /* get the observatory term (if in TDB) */
1274  REAL8 obsTerm = 0; /* observatory term correction from TEMPO2 tt2tb.C */
1275  if ( earth->ttype != TIMECORRECTION_ORIGINAL ) {
1276  REAL8 obsEarth[3];
1277  observatoryEarth( obsEarth, baryinput->site, &baryinput->tgps, earth->gmstRad, earth->delpsi, earth->deleps );
1278 
1279  for ( UINT4 j = 0; j < 3; j++ ) {
1280  obsTerm += obsEarth[j] * earth->velNow[j];
1281  }
1282 
1283  obsTerm /= ( 1.0 - IFTE_LC ) * ( REAL8 )IFTE_K;
1284  }
1285 
1286  /*---------------------------------------------------------------------
1287  * Now including Earth's rotation
1288  *---------------------------------------------------------------------
1289  */
1290  /* calculating effect of luni-solar precession */
1291  REAL8 sinAlphaMinusZA = sin( alpha + earth->tzeA );
1292  REAL8 cosAlphaMinusZA = cos( alpha + earth->tzeA );
1293  REAL8 cosThetaA = cos( earth->thetaA );
1294  REAL8 sinThetaA = sin( earth->thetaA );
1295 
1296  REAL8 cosDeltaSinAlphaMinusZA = sinAlphaMinusZA * cosDelta;
1297 
1298  REAL8 cosDeltaCosAlphaMinusZA = cosAlphaMinusZA * cosThetaA * cosDelta - sinThetaA * sinDelta;
1299 
1300  REAL8 sinDeltaCurt = cosAlphaMinusZA * sinThetaA * cosDelta + cosThetaA * sinDelta;
1301 
1302  /* now taking NdotD, including lunisolar precession, using
1303  Eqs. 3.212-2 of Explan. Supp.
1304  Basic idea for incorporating luni-solar precession
1305  is to change the (alpha,delta) of source to compensate for
1306  Earth's time-changing spin axis.
1307  */
1308  REAL8 cosGastZA = cos( earth->gastRad + longitude - earth->zA );
1309  REAL8 sinGastZA = sin( earth->gastRad + longitude - earth->zA );
1310 
1311  REAL8 rd_NdotD = rd_sinLat * sinDeltaCurt + rd_cosLat * ( cosGastZA * cosDeltaCosAlphaMinusZA + sinGastZA * cosDeltaSinAlphaMinusZA );
1312 
1313  /* delay from center-of-Earth to detector (sec), and its time deriv */
1314  emit->erot = rd_NdotD;
1315  emit->derot = OMEGA * rd_cosLat * ( - sinGastZA * cosDeltaCosAlphaMinusZA + cosGastZA * cosDeltaSinAlphaMinusZA );
1316 
1317  /*--------------------------------------------------------------------------
1318  * Now adding approx nutation (= short-period,forced motion, by definition).
1319  * These two dominant terms, with periods 18.6 yrs (big term) and
1320  * 0.500 yrs (small term),resp., give nutation to around 1 arc sec; see
1321  * p. 120 of Explan. Supp. The forced nutation amplitude
1322  * is around 17 arcsec.
1323  *
1324  * Note the unforced motion or Chandler wobble (called ``polar motion''
1325  * in Explanatory Supp) is not included here. However its amplitude is
1326  * order of (and a somewhat less than) 1 arcsec; see plot on p. 270 of
1327  * Explanatory Supplement to Ast. Alm.
1328  *
1329  * Below correction for nutation from Eq.3.225-2 of Explan. Supp.
1330  * Basic idea is to change the (alpha,delta) of source to
1331  * compensate for Earth's time-changing spin axis.
1332  *--------------------------------------------------------------------------
1333  */
1334  REAL8 delXNut = - earth->delpsi * ( cosDelta * sinAlpha * cosEps0 + sinDelta * sinEps0 );
1335 
1336  REAL8 delYNut = cosDelta * cosAlpha * cosEps0 * earth->delpsi - sinDelta * earth->deleps;
1337 
1338  REAL8 delZNut = cosDelta * cosAlpha * sinEps0 * earth->delpsi + cosDelta * sinAlpha * earth->deleps;
1339 
1340  REAL8 cosGastLong = cos( earth->gastRad + longitude );
1341  REAL8 sinGastLong = sin( earth->gastRad + longitude );
1342 
1343  REAL8 rd_NdotDNut = rd_sinLat * delZNut + rd_cosLat * cosGastLong * delXNut + rd_cosLat * sinGastLong * delYNut;
1344 
1345  emit->erot += rd_NdotDNut;
1346  emit->derot += OMEGA * ( - rd_cosLat * sinGastLong * delXNut + rd_cosLat * cosGastLong * delYNut );
1347 
1348  /* Note erot has a periodic piece (P=one day) AND a constant piece,
1349  since z-component (parallel to North pole) of vector from
1350  Earth-center to detector is constant
1351  */
1352 
1353  /*--------------------------------------------------------------------
1354  * Now adding Shapiro delay. Note according to J. Taylor review article
1355  * on pulsar timing, max value of Shapiro delay (when rays just graze sun)
1356  * is 120 microsec.
1357  *
1358  * Here we calculate Shapiro delay
1359  * for a detector at the center of the Earth.
1360  * Causes errors of order 10^{-4}sec * 4 * 10^{-5} = 4*10^{-9} sec
1361  *--------------------------------------------------------------------
1362  */
1363  REAL8 rsun = 2.322; /*radius of sun in sec */
1364  REAL8 seDotN = earth->se[2] * sinDelta + ( earth->se[0] * cosAlpha + earth->se[1] * sinAlpha ) * cosDelta;
1365  REAL8 dseDotN = earth->dse[2] * sinDelta + ( earth->dse[0] * cosAlpha + earth->dse[1] * sinAlpha ) * cosDelta;
1366 
1367  REAL8 b = sqrt( earth->rse * earth->rse - seDotN * seDotN );
1368  REAL8 db = ( earth->rse * earth->drse - seDotN * dseDotN ) / b;
1369 
1370  /* if gw travels thru interior of Sun*/
1371  if ( ( b < rsun ) && ( seDotN < 0 ) ) {
1372  emit->shapiro = 9.852e-6 * log( ( LAL_AU_SI / LAL_C_SI ) / ( seDotN + sqrt( rsun * rsun + seDotN * seDotN ) ) ) + 19.704e-6 * ( 1.0 - b / rsun );
1373  emit->dshapiro = - 19.704e-6 * db / rsun;
1374  } else { /* else the usual expression*/
1375  emit->shapiro = 9.852e-6 * log( ( LAL_AU_SI / LAL_C_SI ) / ( earth->rse + seDotN ) );
1376  emit->dshapiro = -9.852e-6 * ( earth->drse + dseDotN ) / ( earth->rse + seDotN );
1377  }
1378 
1379  /*--------------------------------------------------------------------
1380  * Now correcting Roemer delay for finite distance to source.
1381  * Timing corrections are order 10 microsec
1382  * for sources closer than about 100 pc = 10^10 sec.
1383  *--------------------------------------------------------------------
1384  */
1385  REAL8 r2 = 0; /* squared dist from SSB to center of earth, in sec^2 */
1386  REAL8 dr2 = 0; /* time deriv of r2 */
1387  REAL8 finiteDistCorr, dfiniteDistCorr; /*correction to Roemer delay due to finite dist D to source; important for D < 100pc */
1388 
1389  if ( baryinput->dInv > 1.0e-11 ) { /* implement if corr. > 1 microsec */
1390  for ( UINT4 j = 0; j < 3; j++ ) {
1391  r2 += earth->posNow[j] * earth->posNow[j];
1392  dr2 += 2.0 * earth->posNow[j] * earth->velNow[j];
1393  }
1394  finiteDistCorr = - 0.5 * ( r2 - emit->roemer * emit->roemer ) * baryinput->dInv;
1395  dfiniteDistCorr = - ( 0.5 * dr2 - emit->roemer * emit->droemer ) * baryinput->dInv;
1396  } else {
1397  finiteDistCorr = 0;
1398  dfiniteDistCorr = 0;
1399  }
1400 
1401  /* -----------------------------------------------------------------------
1402  * Now adding it all up.
1403  * emit.te is pulse emission time in TDB coords
1404  * (up to a constant roughly equal to ligh travel time from source to SSB).
1405  * emit->deltaT = emit.te - tgps.
1406  * -----------------------------------------------------------------------
1407  */
1408  emit->deltaT = emit->roemer + emit->erot + earth->einstein - emit->shapiro + finiteDistCorr + obsTerm;
1409  emit->tDot = 1.0 + emit->droemer + emit->derot + earth->deinstein - emit->dshapiro + dfiniteDistCorr;
1410 
1411  INT4 deltaTint = floor( emit->deltaT );
1412 
1413  if ( ( 1e-9 * tgps[1] + emit->deltaT - deltaTint ) >= 1.e0 ) {
1414  emit->te.gpsSeconds = baryinput->tgps.gpsSeconds + deltaTint + 1;
1415  emit->te.gpsNanoSeconds = floor( 1e9 * ( tgps[1] * 1e-9 + emit->deltaT - deltaTint - 1.0 ) );
1416  } else {
1417  emit->te.gpsSeconds = baryinput->tgps.gpsSeconds + deltaTint;
1418  emit->te.gpsNanoSeconds = floor( 1e9 * ( tgps[1] * 1e-9 + emit->deltaT - deltaTint ) );
1419  }
1420 
1421  for ( UINT4 j = 0; j < 3; j++ ) {
1422  emit->rDetector[j] = earth->posNow[j];
1423  emit->vDetector[j] = earth->velNow[j];
1424  }
1425 
1426  /* Now adding Earth's rotation to rDetector and
1427  vDetector, but NOT yet including effects of
1428  lunisolar prec. or nutation (though DO use gast instead of gmst)
1429  For next 10 years, will give rDetector to 10 microsec and
1430  v/c to 10^-9
1431  */
1432  emit->rDetector[0] += rd_cosLat * cosGastLong;
1433  emit->vDetector[0] += - OMEGA * rd_cosLat * sinGastLong;
1434  emit->rDetector[1] += rd_cosLat * sinGastLong;
1435  emit->vDetector[1] += OMEGA * rd_cosLat * cosGastLong;
1436  emit->rDetector[2] += rd_sinLat;
1437  /*no change to emit->vDetector[2] = component along spin axis, if ignore prec. and nutation */
1438 
1439  // finish buffer handling
1440  // *) if user passed a pointer to NULL, return our internal buffer
1441  if ( buffer && ( *buffer == NULL ) ) {
1442  ( *buffer ) = myBuffer;
1443  }
1444  // *) if passed NULL as 'buffer', then we destroy the internal buffer now
1445  if ( buffer == NULL ) {
1446  XLALFree( myBuffer );
1447  }
1448 
1449  return XLAL_SUCCESS;
1450 
1451 } /* XLALBarycenterOpt() */
1452 
1453 /**
1454  * Function to calculate the precession matrix give Earth nutation values
1455  * depsilon and dpsi for a given MJD time.
1456  *
1457  * This function is a slightly modified version of the TEMPO2 function
1458  * get_precessionMatrix in get_ObsCoord.C (itself translated from the
1459  * TEMPO FORTRAN functions for precession and nutation).
1460  */
1461 void precessionMatrix( REAL8 prn[3][3], /**< [out] The precession matrix */
1462  REAL8 mjd, /**< [in] The UT1 local mean siderial time (in MJD format) */
1463  REAL8 dpsi, /**< [in] The dpsi value for the Earth nutation */
1464  REAL8 deps ) /**< [in] The deps value for the Earth nutation */
1465 {
1466  INT4 i, j;
1467 
1468  /* For precession */
1469  REAL8 t, trad, zeta, z, theta;
1470  static const REAL8 par_zeta[3] = {2306.2181, 0.30188, 0.017998};
1471  static const REAL8 par_z[3] = {2306.2181, 1.09468, 0.018203};
1472  static const REAL8 par_theta[3] = {2004.3109, -0.42665, -0.041833};
1473  static const REAL8 seconds_per_rad = 3600.0 / LAL_PI_180;
1474 
1475  REAL8 czeta, szeta, cz, sz, ctheta, stheta;
1476 
1477  REAL8 nut[3][3], prc[3][3];
1478 
1479  /* cosine and sine of the obliquity of the ecliptic */
1480  const REAL8 ceps = 0.917482062069182;
1481  const REAL8 seps = 0.397777155931914;
1482 
1483  t = ( mjd - 51544.5 ) / 36525.0;
1484  trad = t / seconds_per_rad;
1485 
1486  zeta = trad * ( par_zeta[0] + t * ( par_zeta[1] + t * par_zeta[2] ) );
1487  z = trad * ( par_z[0] + t * ( par_z[1] + t * par_z[2] ) );
1488  theta = trad * ( par_theta[0] + t * ( par_theta[1] + t * par_theta[2] ) );
1489 
1490  czeta = cos( zeta );
1491  szeta = sin( zeta );
1492  cz = cos( z );
1493  sz = sin( z );
1494  ctheta = cos( theta );
1495  stheta = sin( theta );
1496 
1497  prc[0][0] = czeta * ctheta * cz - szeta * sz;
1498  prc[1][0] = czeta * ctheta * sz + szeta * cz;
1499  prc[2][0] = czeta * stheta;
1500  prc[0][1] = -szeta * ctheta * cz - czeta * sz;
1501  prc[1][1] = -szeta * ctheta * sz + czeta * cz;
1502  prc[2][1] = -szeta * stheta;
1503  prc[0][2] = -stheta * cz;
1504  prc[1][2] = -stheta * sz;
1505  prc[2][2] = ctheta;
1506 
1507  nut[0][0] = 1.0;
1508  nut[0][1] = -dpsi * ceps;
1509  nut[0][2] = -dpsi * seps;
1510  nut[1][0] = -nut[0][1];
1511  nut[1][1] = 1.0;
1512  nut[1][2] = -deps;
1513  nut[2][0] = -nut[0][2];
1514  nut[2][1] = -nut[1][2];
1515  nut[2][2] = 1.0;
1516 
1517  for ( i = 0; i < 3; i++ )
1518  for ( j = 0; j < 3; j++ ) {
1519  prn[j][i] = nut[i][0] * prc[0][j] + nut[i][1] * prc[1][j] + nut[i][2] * prc[2][j];
1520  }
1521 }
1522 
1523 /**
1524  * Function to get the observatory site location with respect to the
1525  * centre of the Earth, taking into account precession and nutation.
1526  * This is based on the routines in the TEMPO2 get_ObsCoord.C code
1527  */
1528 void observatoryEarth( REAL8 obsEarth[3], /**< [out] The x, y, z coordinates of the observatory from the centre of the Earth */
1529  const LALDetector det, /**< [in] The LAL detector site */
1530  const LIGOTimeGPS *tgps, /**< [in] The GPS time at the detector */
1531  REAL8 gmst, /**< [in] The Greenwich Mean Sidereal Time */
1532  REAL8 dpsi, /**< [in] dpsi for Earth nutation */
1533  REAL8 deps /**< [in] deps for Earth nutation */
1534  )
1535 {
1536  static REAL8 erad; /* observatory distance from Earth centre */
1537  static REAL8 hlt; /* observatory latitude */
1538  static REAL8 alng; /* observatory longitude */
1539  REAL8 tmjd = 44244. + ( XLALGPSGetREAL8( tgps ) + 51.184 ) / 86400.;
1540 
1541  INT4 j = 0;
1542 
1543  /* note that det.location is in light-seconds */
1544  erad = sqrt( det.location[0] * det.location[0]
1545  + det.location[1] * det.location[1]
1546  + det.location[2] * det.location[2] );
1547  if ( erad == 0.0 ) {
1548  hlt = LAL_PI_2;
1549  } else {
1550  hlt = asin( det.location[2] / erad );
1551  }
1552 
1553  alng = atan2( -det.location[1], det.location[0] );
1554 
1555  static REAL8 siteCoord[3];
1556  REAL8 eeq[3], prn[3][3];
1557 
1558  siteCoord[0] = erad * cos( hlt );
1559  siteCoord[1] = siteCoord[0] * tan( hlt );
1560  siteCoord[2] = alng;
1561 
1562  /* PC,PS equatorial and meridional components of nutations of longitude */
1563  REAL8 toblq = ( tmjd - 5.15445e4 ) / 36525.0;
1564  REAL8 oblq = ( ( ( 1.813e-3 * toblq - 5.9e-4 ) * toblq - 4.6815e1 ) * toblq + 84381.448 ) * LAL_PI_180 / 3600.0;
1565 
1566  REAL8 pc = cos( oblq + deps ) * dpsi;
1567 
1568  /* Compute the local, true sidereal time */
1569  REAL8 ph = gmst + pc - siteCoord[2];
1570 
1571  /* Get X-Y-Z coordinates taking out earth rotation */
1572  eeq[0] = siteCoord[0] * cos( ph );
1573  eeq[1] = siteCoord[0] * sin( ph );
1574  eeq[2] = siteCoord[1];
1575 
1576  /* Now obtain PRN -- the precession matrix */
1577  precessionMatrix( prn, tmjd, dpsi, deps );
1578  /* Calculate the position after precession/nutation*/
1579  for ( j = 0; j < 3 ; j++ ) {
1580  obsEarth[j] = prn[j][0] * eeq[0] + prn[j][1] * eeq[1] + prn[j][2] * eeq[2];
1581  }
1582 }
1583 
1584 /// @}
#define __func__
log an I/O error, i.e.
REAL8 zeta
#define OBLQ
Definition: LALBarycenter.c:24
int j
static double double delta
OMEGA
ParConversion pc[NUM_PARS]
Initialise conversion structure with most allowed TEMPO2 parameter names and conversion functions (co...
int s
double e
double theta
const double sz
const double r2
const double deltaT
#define IFTE_MJD0
Epoch of TCB, TCG and TT in Modified Julian Days.
int XLALBarycenterOpt(EmissionTime *emit, const BarycenterInput *baryinput, const EarthState *earth, BarycenterBuffer **buffer)
Speed optimized version of XLALBarycenter(), should be fully equivalent except for the additional buf...
static void observatoryEarth(REAL8 obsearth[3], const LALDetector det, const LIGOTimeGPS *tgps, REAL8 gmst, REAL8 dpsi, REAL8 deps)
Function to get the observatory site location with respect to the centre of the Earth,...
int XLALBarycenterEarth(EarthState *earth, const LIGOTimeGPS *tGPS, const EphemerisData *edat)
Computes the position and orientation of the Earth, at some arrival time , specified LIGOTimeGPS inp...
Definition: LALBarycenter.c:78
int XLALBarycenter(EmissionTime *emit, const BarycenterInput *baryinput, const EarthState *earth)
Transforms from detector arrival time in GPS (as specified in the LIGOTimeGPS structure) to pulse em...
#define IFTE_LC
Equation 20 of Irwin and Fukushima.
int XLALBarycenterEarthNew(EarthState *earth, const LIGOTimeGPS *tGPS, const EphemerisData *edat, const TimeCorrectionData *tdat, TimeCorrectionType ttype)
Computes the position and orientation of the Earth, at some arrival time, but unlike XLALBarycenterEa...
TimeCorrectionType
Enumerated type denoting the time system type to be produced in the solar system barycentring routine...
Definition: LALBarycenter.h:72
static void precessionMatrix(REAL8 prn[3][3], REAL8 mjd, REAL8 dpsi, REAL8 deps)
Function to calculate the precession matrix give Earth nutation values depsilon and dpsi for a given ...
@ TIMECORRECTION_TEMPO2
Definition: LALBarycenter.h:77
@ TIMECORRECTION_ORIGINAL
Definition: LALBarycenter.h:78
@ TIMECORRECTION_TCB
Definition: LALBarycenter.h:75
@ TIMECORRECTION_TDB
Definition: LALBarycenter.h:74
@ TIMECORRECTION_TEMPO
Definition: LALBarycenter.h:76
#define LAL_PI_2
#define LAL_PI_180
#define LAL_PI
#define LAL_TWOPI
unsigned char BOOLEAN
double REAL8
int16_t INT2
uint32_t UINT4
int32_t INT4
void * XLALCalloc(size_t m, size_t n)
void XLALFree(void *p)
int XLALGPSLeapSeconds(INT4 gpssec)
#define xlalErrno
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EDOM
XLAL_EINVAL
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
pos
n
double alpha
Basic input structure to LALBarycenter.c.
REAL8 alpha
Source right ascension in ICRS J2000 coords (radians).
REAL8 dInv
1/(distance to source), in 1/sec.
LIGOTimeGPS tgps
input GPS arrival time.
REAL8 delta
Source declination in ICRS J2000 coords (radians)
LALDetector site
detector site info.
Basic output structure of LALBarycenterEarth.c.
REAL8 velNow[3]
dimensionless velocity of Earth's center at tgps, extrapolated from JPL DE405 ephemeris
TimeCorrectionType ttype
Time correction type.
REAL8 drse
d(rse)/d(tgps); dimensionless
REAL8 rse
length of vector se[3]; units = sec
REAL8 delpsi
variable describing effect of Earth nutation, at tgps
REAL8 einstein
the einstein delay equiv TDB - TDT or TCB - TDT
REAL8 gmstRad
Greenwich Mean Sidereal Time (GMST) in radians, at tgps.
REAL8 zA
variable describing effect of lunisolar precession, at tgps
REAL8 se[3]
vector that points from Sun to Earth at instant tgps, in DE405 coords; units = sec
REAL8 posNow[3]
Cartesian coords of Earth's center at tgps, extrapolated from JPL DE405 ephemeris; units= sec.
REAL8 tzeA
variable describing effect of lunisolar precession, at tgps
REAL8 gastRad
Greenwich Apparent Sidereal Time, in radians, at tgps; Is basically the angle thru which Earth has sp...
REAL8 dse[3]
d(se[3])/d(tgps); Dimensionless
REAL8 deinstein
d(einstein)/d(tgps)
REAL8 thetaA
variable describing effect of lunisolar precession, at tgps
REAL8 deleps
variable describing effect of Earth nutation, at tgps
Basic output structure produced by LALBarycenter.c.
REAL8 derot
d(erot)/d(tgps)
REAL8 deltaT
(TDB) - (GPS)
REAL8 roemer
the Roemer delay
REAL8 dshapiro
d(Shapiro)/d(tgps)
REAL8 rDetector[3]
Cartesian coords (0=x,1=y,2=z) of detector position at $t_a$ (GPS), in ICRS J2000 coords.
REAL8 shapiro
the Shapiro delay
REAL8 erot
Earth rotation delay.
LIGOTimeGPS te
pulse emission time (TDB); also sometimes called `‘arrival time (TDB) of same wavefront at SSB’'
REAL8 tDot
d(emission time in TDB)/d(arrival time in GPS)
REAL8 vDetector[3]
REAL8 droemer
d(Roemer)/d(tgps)
This structure contains all information about the center-of-mass positions of the Earth and Sun,...
REAL8 location[3]
INT4 gpsNanoSeconds
This structure will contain a vector of time corrections used during conversion from TT to TDB/TCB/Te...
REAL8 latitude
geocentric (not geodetic!!) longitude of detector vertex
Definition: LALBarycenter.c:38
REAL8 sinLat
geocentric latitude of detector vertex
Definition: LALBarycenter.c:39
REAL8 rd_cosLat
rd * sin(latitude)
Definition: LALBarycenter.c:42
REAL8 rd_sinLat
cos(latitude);
Definition: LALBarycenter.c:41
REAL8 cosLat
sin(latitude)
Definition: LALBarycenter.c:40
REAL8 longitude
distance 'rd' from center of Earth, in light seconds
Definition: LALBarycenter.c:37
-------— internal buffer type for optimized Barycentering function -------—
Definition: LALBarycenter.c:27
REAL8 sinAlpha
Definition: LALBarycenter.c:28
REAL8 cosDelta
sin(delta)
Definition: LALBarycenter.c:31
REAL8 cosAlpha
sin(alpha)
Definition: LALBarycenter.c:29
REAL8 sinDelta
cos(alpha)
Definition: LALBarycenter.c:30
internal (opaque) buffer type for optimized Barycentering function
Definition: LALBarycenter.c:45
fixed_site_t fixed_site
buffered detector site
Definition: LALBarycenter.c:51
REAL8 delta
buffered sky-location: right-ascension in rad
Definition: LALBarycenter.c:47
fixed_sky_t fixed_sky
buffered sky-location: declination in rad
Definition: LALBarycenter.c:48
BOOLEAN active
fixed-site buffered quantities
Definition: LALBarycenter.c:53
LALDetector site
fixed-sky buffered quantities
Definition: LALBarycenter.c:50