LALPulsar  6.1.0.1-c9a8ef6
HeterodynedPulsarModel.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2018 Matthew 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 #include <lal/HeterodynedPulsarModel.h>
21 
22 /** Macro to round a value to the nearest integer. */
23 #define ROUND(x) (floor(x+0.5))
24 
25 /** Macro to square a value. */
26 #define SQUARE(x) ( (x) * (x) )
27 
28 /**
29 * \brief The phase evolution difference compared to a heterodyned phase (for a pulsar)
30 *
31 * This function will calculate the difference in the phase evolution of a
32 * source at a particular sky location as observed in a detector on Earth
33 * compared with that used to heterodyne (or SpectralInterpolate) the data. If
34 * the phase evolution is described by a Taylor expansion:
35 * \f[
36 * \phi(T) = \sum_{k=1}^n \frac{f^{(k-1)}}{k!} T^k,
37 * \f]
38 * where \f$ f^{(x)} \f$ is the xth time derivative of the gravitational-wave
39 * frequency, and \f$ T \f$ is the pulsar proper time, then the phase difference
40 * is given by
41 * \f[
42 * \Delta\phi(t) = \sum_{k=1}^n \left( \frac{\Delta f^{(k-1)}}{k!}(t+\delta t_1)^k + \frac{f^{(k-1)}_2}{k!} \sum_{i=0}^{i<k} \left(\begin{array}{c}k \\ i\end{array}\right) (\Delta t)^{k-i} (t+\delta t_1)^i \right),
43 * \f]
44 * where \f$ t \f$ is the signal arrival time at the detector minus the given
45 * pulsar period epoch, \f$ \delta t_1 \f$ is the barycentring time delay (from
46 * both solar system and binary orbital effects) calculated at the heterodyned
47 * values, \f$ \Delta f^{(x)} = f_2^{(x)}-f1^{(x)} \f$ is the diffence in
48 * frequency (derivative) between the current value ( \f$ f_2^{(x)} \f$ ) and the
49 * heterodyne value ( \f$ f_1^{(x)} \f$ ), and
50 * \f$ \Delta t = \delta t_2 - \delta t_1 \f$ is the difference between the
51 * barycentring time delay calculated at the current values ( \f$ \delta t_1 \f$ )
52 * and the heterodyned values. Frequency time derivatives up to any order are
53 * allowed. The pulsar proper time is calculated by correcting the time of
54 * arrival at Earth, \f$ t \f$ to the solar system barycentre and if necessary
55 * the binary system barycenter, so
56 * \f$ T = t + \delta{}t_{\rm SSB} + \delta{}t_{\rm BSB} \f$ .
57 *
58 * In this function the time delay needed to correct to the solar system
59 * barycenter is only calculated if required, i.e., if an update is required
60 * due to a change in the sky position. The same is true for the binary system
61 * time delay, which is only calculated if it needs updating due to a change in
62 * the binary system parameters. The function will also calculate any phase
63 * evolution due to pulsar glitch parameters and/or \c FITWAVES parameters
64 * (parameters that define sinusoidal terms used to represent strong red noise
65 * in the signal) if required.
66 *
67 * This function can just return the phase evolution (and not phase evolution
68 * difference) if \c ssbdts, \c bsbdts, and \c origparams are NULL, which will
69 * be based on the parameters set in the \c params structure.
70 *
71 * \param params [in] A set of pulsar parameters
72 * \param origparams [in] The original parameters used to heterodyne the data
73 * \param datatimes [in] A vector of GPS times at which to calculate the phase difference
74 * \param freqfactor [in] The multiplicative factor on the pulsar frequency for a particular model
75 * \param ssbdts [in] The vector of SSB time delays used for the original heterodyne. If this is
76 * \c NULL then the SSB delay for the given position will be calculated.
77 * \param calcSSBDelay [in] Set to a non-zero value if the SSB delay needs to be calculated. This
78 * would be required if using an updated sky position compared to that used for the heterodyne, or
79 * if calculating the full phase evolution rather than a phase difference.
80 * \param bsbdts [in] The vector of BSB time delays used for the original heterodyne. If this is
81 * \c NULL then the BSB delay for the given binary parameters will be calculated.
82 * \param calcBSBDelay [in] Set to a non-zero value if the BSB delay needs to be calculated. This
83 * would be required if using updated binary parameters compared to that used for the heterodyne, or
84 * if calculating the full phase evolution rather than a phase difference.
85 * \param glphase [in] The vector of the glitch phase evolution (in EM cycles) used in the original
86 * heterodyne. If this is \c NULL then the glitch phase for the given glitch parameters will be
87 * calculated.
88 * \param calcglphase [in] Set to a non-zero value if the glitch phase needs to be calculated. This
89 * would be required if using a set of updated glitch parameters compared to that used for the
90 * heterodyne, or if calculating the full phase evolution rather than a phase difference.
91 * \param fitwavesphase [in] The vector of the phase evolution (in EM cycles) for any FITWAVES
92 * (sinusoids used to fit red noise) parameters used in the original heterodyne. If this is \c NULL
93 * then the FITWAVES phase for the given parameters will be calculated.
94 * \param calcfitwaves [in] Set to a non-zero value if the FITWAVES phase needs to be calculated.
95 * This would be required if using an updated set of FITWAVES parameters, or if calculating the
96 * full phase evolution rather than a phase difference.
97 * \param detector [in] A pointer to a \c LALDetector structure for a particular detector
98 * \param ephem [in] A pointer to an \c EphemerisData structure containing solar system ephemeris information
99 * \param tdat [in] A pointer to a \c TimeCorrectionData structure containing time system correction information
100 * \param ttype [in] The \c TimeCorrectionType value
101 *
102 * \return A vector of rotational phase difference values (in cycles NOT radians)
103 *
104 * \sa XLALHeterodynedPulsarGetSSBDelay
105 * \sa XLALHeterodynedPulsarGetBSBDelay
106 */
108  PulsarParameters *origparams,
109  const LIGOTimeGPSVector *datatimes,
110  REAL8 freqfactor,
111  REAL8Vector *ssbdts,
112  UINT4 calcSSBDelay,
113  REAL8Vector *bsbdts,
114  UINT4 calcBSBDelay,
115  REAL8Vector *glphase,
116  UINT4 calcglphase,
117  REAL8Vector *fitwavesphase,
118  UINT4 calcfitwaves,
119  const LALDetector *detector,
120  const EphemerisData *ephem,
121  const TimeCorrectionData *tdat,
122  TimeCorrectionType ttype )
123 {
124  /* check inputs */
125  XLAL_CHECK_NULL( params != NULL, XLAL_EFUNC, "PulsarParameters must not be NULL" );
126  XLAL_CHECK_NULL( datatimes != NULL, XLAL_EFUNC, "datatimes must not be NULL" );
127  XLAL_CHECK_NULL( freqfactor > 0., XLAL_EFUNC, "freqfactor must be greater than zero" );
128  XLAL_CHECK_NULL( detector != NULL, XLAL_EFUNC, "LALDetector must not be NULL" );
129  XLAL_CHECK_NULL( ephem != NULL, XLAL_EFUNC, "EphemerisData must not be NULL" );
130 
131  UINT4 i = 0, j = 0, k = 0, length = 0, nfreqs = 0;
132 
133  REAL8 DT = 0., deltat = 0., deltatpow = 0., deltatpowinner = 1., taylorcoeff = 1., Ddelay = 0., Ddelaypow = 0.;
134 
135  REAL8Vector *phis = NULL, *dts = NULL, *fixdts = NULL, *bdts = NULL, *fixbdts = NULL, *fixglph = NULL, *glph = NULL, *fixfitwavesph = NULL, *fitwavesph = NULL;
136 
137  REAL8 pepoch = PulsarGetREAL8ParamOrZero( params, "PEPOCH" ); /* time of ephem info */
138  REAL8 T0 = pepoch, pepochorig = pepoch;
139  REAL8 *deltafs = NULL, *frequpdate = NULL;
140 
141  length = datatimes->length;
142 
143  /* allocate memory for phases */
144  phis = XLALCreateREAL8Vector( length );
145 
146  /* get solar system barycentring time delays */
147  fixdts = ssbdts;
148  if ( calcSSBDelay ) {
149  if ( origparams != NULL && ssbdts != NULL ) {
150  dts = XLALHeterodynedPulsarGetSSBDelay( params, datatimes, detector, ephem, tdat, ttype );
151  } else {
152  fixdts = XLALHeterodynedPulsarGetSSBDelay( params, datatimes, detector, ephem, tdat, ttype );
153  }
154  XLAL_CHECK_NULL( length == fixdts->length, XLAL_EFUNC, "Lengths of time stamp vector and SSB delay vector are not the same" );
155  }
156 
157  /* get the binary system barycentring time delays */
158  fixbdts = bsbdts;
159  if ( calcBSBDelay ) {
160  REAL8Vector *whichssb = dts != NULL ? dts : fixdts;
161  if ( origparams != NULL && bsbdts != NULL ) {
162  bdts = XLALHeterodynedPulsarGetBSBDelay( params, datatimes, whichssb, ephem );
163  } else {
164  fixbdts = XLALHeterodynedPulsarGetBSBDelay( params, datatimes, whichssb, ephem );
165  }
166  XLAL_CHECK_NULL( length == fixbdts->length, XLAL_EFUNC, "Lengths of time stamp vector and BSB delay vector are not the same" );
167  }
168 
169  /* get the glitch parameter phase evolution */
170  fixglph = glphase;
171  if ( calcglphase ) {
172  const REAL8Vector *whichssb = dts != NULL ? dts : fixdts;
173  const REAL8Vector *whichbsb = bdts != NULL ? bdts : fixbdts;
174  if ( origparams != NULL && glphase != NULL ) {
175  glph = XLALHeterodynedPulsarGetGlitchPhase( params, datatimes, whichssb, whichbsb );
176  } else {
177  fixglph = XLALHeterodynedPulsarGetGlitchPhase( params, datatimes, whichssb, whichbsb );
178  }
179  }
180 
181  /* set the "new" frequencies, with zeros where required */
182  if ( origparams != NULL ) {
183  const REAL8Vector *tmpvec = PulsarGetREAL8VectorParam( origparams, "F" );
184  const REAL8Vector *freqs = PulsarGetREAL8VectorParam( params, "F" );
185  nfreqs = tmpvec->length >= freqs->length ? tmpvec->length : freqs->length;
186  pepochorig = PulsarGetREAL8ParamOrZero( origparams, "PEPOCH" );
187  } else {
188  const REAL8Vector *freqs = PulsarGetREAL8VectorParam( params, "F" );
189  nfreqs = freqs->length;
190  }
191 
192  frequpdate = XLALCalloc( nfreqs, sizeof( REAL8 ) );
193  const REAL8Vector *freqsu = PulsarGetREAL8VectorParam( params, "F" );
194  /* initialise deltafs to zero */
195  deltafs = XLALCalloc( nfreqs, sizeof( REAL8 ) );
196  deltat = ( pepochorig - pepoch );
197  deltatpow = deltat;
198  for ( i = 0; i < freqsu->length; i++ ) {
199  frequpdate[i] = freqsu->data[i];
200 
201  /* if epochs are different update "new" frequency to heterodyne epoch */
202  if ( pepoch != pepochorig ) {
203  REAL8 deltatpowu = deltatpow;
204  for ( j = i + 1; i < freqsu->length; j++ ) {
205  frequpdate[i] += ( freqsu->data[j] * deltatpowu ) / gsl_sf_fact( j - i );
206  deltatpowu *= deltat;
207  }
208  deltatpow *= deltat;
209  }
210  }
211 
212  /* get vector of frequencies and frequency differences */
213  if ( origparams != NULL ) {
214  if ( PulsarCheckParam( origparams, "F" ) ) {
215  const REAL8Vector *tmpvec = PulsarGetREAL8VectorParam( origparams, "F" );
216 
217  for ( i = 0; i < nfreqs; i++ ) {
218  /* deal with cases where there are fewer frequency derivatives in the original heterodyne file */
219  if ( i >= tmpvec->length ) {
220  deltafs[i] = frequpdate[i];
221  } else {
222  deltafs[i] = frequpdate[i] - tmpvec->data[i];
223  }
224  }
225  } else {
226  XLAL_ERROR_NULL( XLAL_EINVAL, "No frequencies given in heterodyned parameter file!" );
227  }
228  } else {
229  /* set deltafs to (negative) frequencies */
230  for ( i = 0; i < nfreqs; i++ ) {
231  deltafs[i] = -frequpdate[i];
232  }
233  }
234 
235  /* get FITWAVES phase */
236  fixfitwavesph = fitwavesphase;
237  if ( calcfitwaves ) {
238  const REAL8Vector *whichssb = dts != NULL ? dts : fixdts;
239  if ( origparams != NULL && fitwavesphase != NULL ) {
240  fitwavesph = XLALHeterodynedPulsarGetFITWAVESPhase( params, datatimes, whichssb, frequpdate[0] );
241  } else {
242  fixfitwavesph = XLALHeterodynedPulsarGetFITWAVESPhase( params, datatimes, whichssb, frequpdate[0] );
243  }
244  }
245 
246  for ( i = 0; i < length; i++ ) {
247  REAL8 deltaphi = 0., innerphi = 0.; /* change in phase */
248  Ddelay = 0.; /* change in SSB/BSB delay */
249 
250  REAL8 realT = XLALGPSGetREAL8( &datatimes->data[i] ); /* time of data */
251  DT = realT - T0; /* time diff between data and start of data */
252 
253  /* get difference in solar system barycentring time delays */
254  deltat = DT;
255  if ( dts != NULL ) {
256  Ddelay += ( dts->data[i] - fixdts->data[i] );
257  }
258  if ( fixdts != NULL ) {
259  deltat += fixdts->data[i];
260  }
261 
262  /* get difference in binary system barycentring time delays */
263  if ( bdts != NULL && fixbdts != NULL ) {
264  Ddelay += ( bdts->data[i] - fixbdts->data[i] );
265  }
266  if ( fixbdts != NULL ) {
267  deltat += fixbdts->data[i];
268  }
269 
270  /* get the change in phase (compared to the heterodyned phase) */
271  deltatpow = deltat;
272  for ( j = 0; j < nfreqs; j++ ) {
273  taylorcoeff = gsl_sf_fact( j + 1 );
274  deltaphi += deltafs[j] * deltatpow / taylorcoeff;
275  if ( Ddelay != 0. ) {
276  innerphi = 0.;
277  deltatpowinner = 1.; /* this starts as one as it is first raised to the power of zero */
278  Ddelaypow = pow( Ddelay, j + 1 );
279  for ( k = 0; k < j + 1; k++ ) {
280  innerphi += gsl_sf_choose( j + 1, k ) * Ddelaypow * deltatpowinner;
281  deltatpowinner *= deltat; /* raise power */
282  Ddelaypow /= Ddelay; /* reduce power */
283  }
284  deltaphi += innerphi * frequpdate[j] / taylorcoeff;
285  }
286  deltatpow *= deltat;
287  }
288 
289  /* get change in phase from glitches */
290  if ( glph != NULL && fixglph != NULL ) {
291  deltaphi += ( glph->data[i] - fixglph->data[i] );
292  } else if ( fixglph != NULL ) {
293  deltaphi += fixglph->data[i];
294  }
295 
296  /* get change in phase from FITWAVES parameters */
297  if ( fitwavesph != NULL && fixfitwavesph != NULL ) {
298  deltaphi += ( fitwavesph->data[i] - fixfitwavesph->data[i] );
299  } else if ( fixfitwavesph != NULL ) {
300  deltaphi += fixfitwavesph->data[i];
301  }
302 
303  deltaphi *= freqfactor; /* multiply by frequency factor */
304  phis->data[i] = deltaphi - floor( deltaphi ); /* only need to keep the fractional part of the phase */
305  }
306 
307  /* free memory */
308  if ( dts != NULL ) {
309  XLALDestroyREAL8Vector( dts );
310  }
311  if ( bdts != NULL ) {
312  XLALDestroyREAL8Vector( bdts );
313  }
314  if ( ssbdts == NULL ) {
315  XLALDestroyREAL8Vector( fixdts );
316  }
317  if ( bsbdts == NULL ) {
318  XLALDestroyREAL8Vector( fixbdts );
319  }
320  if ( glph != NULL ) {
321  XLALDestroyREAL8Vector( glph );
322  }
323  if ( glphase == NULL ) {
324  XLALDestroyREAL8Vector( fixglph );
325  }
326  if ( fitwavesph != NULL ) {
327  XLALDestroyREAL8Vector( fitwavesph );
328  }
329  if ( fitwavesphase == NULL ) {
330  XLALDestroyREAL8Vector( fixfitwavesph );
331  }
332  XLALFree( deltafs );
333  XLALFree( frequpdate );
334 
335  return phis;
336 }
337 
338 
339 /**
340  * \brief Computes the delay between a GPS time at Earth and the solar system barycentre
341  *
342  * This function calculates the time delay between a GPS time at a specific
343  * location (e.g., a gravitational-wave detector) on Earth and the solar system
344  * barycentre. The delay consists of three components: the geometric time delay
345  * (Roemer delay) \f$ t_R = \mathbf{r}(t)\hat{n}/c \f$ (where \f$ \mathbf{r}(t) \f$
346  * is the detector's position vector at time \f$ t \f$ ), the special relativistic
347  * Einstein delay \f$ t_E \f$ , and the general relativistic Shapiro delay
348  * \f$ t_S \f$ .
349  *
350  * \param pars [in] A set of pulsar parameters
351  * \param datatimes [in] A vector of GPS times at Earth
352  * \param detector [in] Information on the detector position on the Earth
353  * \param ephem [in] Information on the solar system ephemeris
354  * \param tdat [in] Informaion on the time system corrections
355  * \param ttype [in] The type of time system corrections to perform
356  *
357  * \return A vector of time delays in seconds
358  *
359  * \sa XLALBarycenter
360  * \sa XLALBarycenterEarthNew
361  */
363  const LIGOTimeGPSVector *datatimes,
364  const LALDetector *detector,
365  const EphemerisData *ephem,
366  const TimeCorrectionData *tdat,
367  TimeCorrectionType ttype )
368 {
369  /* check inputs */
370  XLAL_CHECK_NULL( pars != NULL, XLAL_EFUNC, "PulsarParameters must not be NULL" );
371  XLAL_CHECK_NULL( datatimes != NULL, XLAL_EFUNC, "datatimes must not be NULL" );
372  XLAL_CHECK_NULL( detector != NULL, XLAL_EFUNC, "LALDetector must not be NULL" );
373  XLAL_CHECK_NULL( ephem != NULL, XLAL_EFUNC, "EphemerisData must not be NULL" );
374 
375  INT4 i = 0, length = 0;
376 
377  BarycenterInput bary;
378 
379  REAL8Vector *dts = NULL;
380 
381  /* copy barycenter and ephemeris data */
382  bary.site.location[0] = detector->location[0] / LAL_C_SI;
383  bary.site.location[1] = detector->location[1] / LAL_C_SI;
384  bary.site.location[2] = detector->location[2] / LAL_C_SI;
385 
386  REAL8 ra = 0.;
387  if ( PulsarCheckParam( pars, "RA" ) ) {
388  ra = PulsarGetREAL8Param( pars, "RA" );
389  } else if ( PulsarCheckParam( pars, "RAJ" ) ) {
390  ra = PulsarGetREAL8Param( pars, "RAJ" );
391  } else {
392  XLAL_ERROR_NULL( XLAL_EINVAL, "No source right ascension specified!" );
393  }
394  REAL8 dec = 0.;
395  if ( PulsarCheckParam( pars, "DEC" ) ) {
396  dec = PulsarGetREAL8Param( pars, "DEC" );
397  } else if ( PulsarCheckParam( pars, "DECJ" ) ) {
398  dec = PulsarGetREAL8Param( pars, "DECJ" );
399  } else {
400  XLAL_ERROR_NULL( XLAL_EINVAL, "No source declination specified!" );
401  }
402  REAL8 pmra = PulsarGetREAL8ParamOrZero( pars, "PMRA" );
403  REAL8 pmdec = PulsarGetREAL8ParamOrZero( pars, "PMDEC" );
404  REAL8 pepoch = PulsarGetREAL8ParamOrZero( pars, "PEPOCH" );
405  REAL8 posepoch = PulsarGetREAL8ParamOrZero( pars, "POSEPOCH" );
406 
407  REAL8 cgw = PulsarGetREAL8ParamOrZero( pars, "CGW" );
408 
409  REAL8 dist = 0.; /* distance in light seconds */
410  /* set distance (a DIST param takes precedence over PX) */
411  if ( PulsarCheckParam( pars, "DIST" ) ) {
412  dist = PulsarGetREAL8Param( pars, "DIST" ) / LAL_C_SI;
413  } else if ( PulsarCheckParam( pars, "PX" ) ) {
414  dist = ( LAL_AU_SI / LAL_C_SI ) / PulsarGetREAL8Param( pars, "PX" );
415  }
416 
417  /* set the position and frequency epochs if not already set */
418  if ( pepoch == 0. && posepoch != 0. ) {
419  pepoch = posepoch;
420  } else if ( posepoch == 0. && pepoch != 0. ) {
421  posepoch = pepoch;
422  }
423 
424  length = datatimes->length;
425 
426  /* allocate memory for times delays */
427  dts = XLALCreateREAL8Vector( length );
428 
429  /* set 1/distance if distance is given */
430  if ( dist != 0. ) {
431  bary.dInv = 1. / dist;
432  } else {
433  bary.dInv = 0.;
434  }
435 
436  /* make sure ra and dec are wrapped within 0--2pi and -pi.2--pi/2 respectively */
437  ra = fmod( ra, LAL_TWOPI );
438  REAL8 absdec = fabs( dec );
439  if ( absdec > LAL_PI_2 ) {
440  UINT4 nwrap = floor( ( absdec + LAL_PI_2 ) / LAL_PI );
441  dec = ( dec > 0 ? 1. : -1. ) * ( nwrap % 2 == 1 ? -1. : 1. ) * ( fmod( absdec + LAL_PI_2, LAL_PI ) - LAL_PI_2 );
442  ra = fmod( ra + ( REAL8 )nwrap * LAL_PI, LAL_TWOPI ); /* move RA by pi */
443  }
444 
445  EarthState earth;
446  EmissionTime emit;
447  for ( i = 0; i < length; i++ ) {
448  REAL8 realT = XLALGPSGetREAL8( &datatimes->data[i] );
449 
450  bary.tgps = datatimes->data[i];
451  bary.delta = dec + ( realT - posepoch ) * pmdec;
452  bary.alpha = ra + ( realT - posepoch ) * pmra / cos( bary.delta );
453 
454  /* call barycentring routines */
455  XLAL_CHECK_NULL( XLALBarycenterEarthNew( &earth, &bary.tgps, ephem, tdat, ttype ) == XLAL_SUCCESS, XLAL_EFUNC, "Barycentring routine failed" );
456  XLAL_CHECK_NULL( XLALBarycenter( &emit, &bary, &earth ) == XLAL_SUCCESS, XLAL_EFUNC, "Barycentring routine failed" );
457 
458  if ( cgw > 0.0 ) {
459  /* account for the speed of GWs not being the same a the speed of light
460  NOTE: we are only accounting for this in the Roemer delay */
461  dts->data[i] = ( emit.deltaT - emit.roemer ) + ( emit.roemer / cgw );
462  } else {
463  dts->data[i] = emit.deltaT;
464  }
465  }
466 
467  return dts;
468 }
469 
470 
471 /**
472  * \brief Computes the delay between a pulsar in a binary system and the barycentre of the system
473  *
474  * This function uses \c XLALBinaryPulsarDeltaTNew to calculate the time delay
475  * between for a pulsar in a binary system between the time at the pulsar and
476  * the time at the barycentre of the system. This includes Roemer delays and
477  * relativistic delays. The orbit may be described by different models and can
478  * be purely Keplarian or include various relativistic corrections.
479  *
480  * \param pars [in] A set of pulsar parameters
481  * \param datatimes [in] A vector of GPS times
482  * \param dts [in] A vector of solar system barycentre time delays
483  * \param edat [in] Solar system ephemeris information
484  *
485  * \return A vector of time delays in seconds
486  *
487  * \sa XLALBinaryPulsarDeltaTNew
488  */
490  const LIGOTimeGPSVector *datatimes,
491  const REAL8Vector *dts,
492  const EphemerisData *edat )
493 {
494  /* check inputs */
495  XLAL_CHECK_NULL( pars != NULL, XLAL_EFUNC, "PulsarParameters must not be NULL" );
496  XLAL_CHECK_NULL( datatimes != NULL, XLAL_EFUNC, "datatimes must not be NULL" );
497  XLAL_CHECK_NULL( dts != NULL, XLAL_EFUNC, "SSB delay times must not be NULL" );
498  XLAL_CHECK_NULL( edat != NULL, XLAL_EFUNC, "EphemerisData must not be NULL" );
499 
500  REAL8 cgw = PulsarGetREAL8ParamOrZero( pars, "CGW" );
501 
502  REAL8Vector *bdts = NULL;
503  BinaryPulsarInput binput;
504  BinaryPulsarOutput boutput;
505  EarthState earth;
506 
507  INT4 i = 0, length = datatimes->length;
508 
509  bdts = XLALCreateREAL8Vector( length );
510  memset( bdts->data, 0, bdts->length * sizeof( REAL8 ) ); // set to zeros
511 
512  /* check whether there's a binary model */
513  if ( PulsarCheckParam( pars, "BINARY" ) ) {
514  for ( i = 0; i < length; i++ ) {
515  binput.tb = XLALGPSGetREAL8( &datatimes->data[i] ) + dts->data[i];
516 
517  XLALGetEarthPosVel( &earth, edat, &datatimes->data[i] );
518 
519  binput.earth = earth; /* current Earth state */
520  XLALBinaryPulsarDeltaTNew( &boutput, &binput, pars );
521 
522  if ( cgw > 0. ) {
523  /* account for the speed of GWs not being the same as the speed of light
524  * NOTE: here we have to assume that the Roemer delay, which is effected
525  * by the speed difference is dominating the delay term. */
526  bdts->data[i] = boutput.deltaT / cgw;
527  } else {
528  bdts->data[i] = boutput.deltaT;
529  }
530  }
531  }
532  return bdts;
533 }
534 
535 
536 /**
537  * \brief Get the position and velocity of the Earth at a given time
538  *
539  * This function will get the position and velocity of the Earth from the
540  * ephemeris data at the time t. It will be returned in an EarthState
541  * structure. This is based on the start of the \c XLALBarycenterEarth
542  * function.
543  *
544  * \param earth [out] The returned \c EarthState structure containing the Earth's position and velocity
545  * \param edat [in] The solar system ephemeris data
546  * \param tGPS [in] A \c LIGOTimeGPS structure containing a GPS time
547  *
548  * \sa XLALBarycenterEarth
549  */
551  const EphemerisData *edat,
552  const LIGOTimeGPS *tGPS )
553 {
554  REAL8 tgps[2];
555 
556  REAL8 t0e; /* time since first entry in Earth ephem. table */
557  INT4 ientryE; /* entry in look-up table closest to current time, tGPS */
558 
559  REAL8 tinitE; /* time (GPS) of first entry in Earth ephem table */
560  REAL8 tdiffE; /* current time tGPS minus time of nearest entry in Earth ephem look-up table */
561  REAL8 tdiff2E; /* tdiff2 = tdiffE * tdiffE */
562 
563  INT4 j;
564 
565  /* check input */
566  if ( !earth || !tGPS || !edat || !edat->ephemE || !edat->ephemS ) {
567  XLAL_ERROR_VOID( XLAL_EINVAL, "Invalid NULL input 'earth', 'tGPS', 'edat','edat->ephemE' or 'edat->ephemS'" );
568  }
569 
570  tgps[0] = ( REAL8 )tGPS->gpsSeconds; /* convert from INT4 to REAL8 */
571  tgps[1] = ( REAL8 )tGPS->gpsNanoSeconds;
572 
573  tinitE = edat->ephemE[0].gps;
574 
575  t0e = tgps[0] - tinitE;
576  ientryE = ROUND( t0e / edat->dtEtable ); /* finding Earth table entry */
577 
578  if ( ( ientryE < 0 ) || ( ientryE >= edat->nentriesE ) ) {
579  XLAL_ERROR_VOID( XLAL_EDOM, "Input GPS time %f outside of Earth ephem range [%f, %f]\n", tgps[0], tinitE, tinitE +
580  edat->nentriesE * edat->dtEtable );
581  }
582 
583  /* tdiff is arrival time minus closest Earth table entry; tdiff can be pos. or neg. */
584  tdiffE = t0e - edat->dtEtable * ientryE + tgps[1] * 1.e-9;
585  tdiff2E = tdiffE * tdiffE;
586 
587  REAL8 *pos = edat->ephemE[ientryE].pos;
588  REAL8 *vel = edat->ephemE[ientryE].vel;
589  REAL8 *acc = edat->ephemE[ientryE].acc;
590 
591  for ( j = 0; j < 3; j++ ) {
592  earth->posNow[j] = pos[j] + vel[j] * tdiffE + 0.5 * acc[j] * tdiff2E;
593  earth->velNow[j] = vel[j] + acc[j] * tdiffE;
594  }
595 }
596 
597 
598 /**
599  * \brief Computes the phase evolution due to the presence of glitches
600  *
601  * This function calculates the phase offset due to the presence on pulsar
602  * glitches. This is based on the equations in the \c formResiduals.C file of
603  * TEMPO2 from Eqn. 1 of \cite Yu2013 .
604  *
605  * \param params [in] A set of pulsar parameters
606  * \param datatimes [in] A vector of GPS times at Earth
607  * \param ssbdts [in] A vector of solar system barycentre time delays
608  * \param bsbdts [in] A vector of binary system barycentre time delays
609  *
610  * \return A vector of (EM) phases in cycles
611  */
613  const LIGOTimeGPSVector *datatimes,
614  const REAL8Vector *ssbdts,
615  const REAL8Vector *bsbdts )
616 {
617  /* check inputs */
618  XLAL_CHECK_NULL( params != NULL, XLAL_EFUNC, "PulsarParameters must not be NULL" );
619  XLAL_CHECK_NULL( datatimes != NULL, XLAL_EFUNC, "datatimes must not be NULL" );
620  XLAL_CHECK_NULL( ssbdts != NULL, XLAL_EFUNC, "ssbdts must not be NULL" );
621  XLAL_CHECK_NULL( ssbdts->length == datatimes->length, XLAL_EFUNC, "datatimes and ssbdts must be the same length" );
622  if ( bsbdts != NULL ) {
623  XLAL_CHECK_NULL( ssbdts->length == bsbdts->length, XLAL_EFUNC, "bsbdts and ssbdts must be the same length" );
624  }
625 
626  UINT4 i = 0, length = 0;
627  REAL8Vector *glphase = NULL;
628  REAL8 tdt = 0.;
629 
630  length = datatimes->length;
631 
632  /* allocate memory for phases */
633  glphase = XLALCreateREAL8Vector( length );
634  memset( glphase->data, 0, glphase->length * sizeof( REAL8 ) ); // set to zeros
635 
636  /* see if pulsar has glitch parameters */
637  if ( PulsarCheckParam( params, "GLEP" ) ) {
638  /* in case not all parameters are set and they are not all the same length, copy into arrays
639  of the same length that are initialised to zero - all glitches must have an epoch */
640  const REAL8Vector *glep = PulsarGetREAL8VectorParam( params, "GLEP" );
641  UINT4 glnum = glep->length;
642 
643  /* get phase offsets */
644  REAL8 *glph = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
645  if ( PulsarCheckParam( params, "GLPH" ) ) {
646  const REAL8Vector *tmpvec = PulsarGetREAL8VectorParam( params, "GLPH" );
647  memcpy( glph, tmpvec->data, tmpvec->length * sizeof( REAL8 ) );
648  }
649 
650  /* get frequencies offsets */
651  REAL8 *glf0 = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
652  if ( PulsarCheckParam( params, "GLF0" ) ) {
653  const REAL8Vector *tmpvec = PulsarGetREAL8VectorParam( params, "GLF0" );
654  memcpy( glf0, tmpvec->data, tmpvec->length * sizeof( REAL8 ) );
655  }
656 
657  /* get frequency derivative offsets */
658  REAL8 *glf1 = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
659  if ( PulsarCheckParam( params, "GLF1" ) ) {
660  const REAL8Vector *tmpvec = PulsarGetREAL8VectorParam( params, "GLF1" );
661  memcpy( glf1, tmpvec->data, tmpvec->length * sizeof( REAL8 ) );
662  }
663 
664  /* get second frequency derivative offsets */
665  REAL8 *glf2 = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
666  if ( PulsarCheckParam( params, "GLF2" ) ) {
667  const REAL8Vector *tmpvec = PulsarGetREAL8VectorParam( params, "GLF2" );
668  memcpy( glf2, tmpvec->data, tmpvec->length * sizeof( REAL8 ) );
669  }
670 
671  /* get decaying frequency component offset derivative */
672  REAL8 *glf0d = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
673  if ( PulsarCheckParam( params, "GLF0D" ) ) {
674  const REAL8Vector *tmpvec = PulsarGetREAL8VectorParam( params, "GLF0D" );
675  memcpy( glf0d, tmpvec->data, tmpvec->length * sizeof( REAL8 ) );
676  }
677 
678  /* get decaying frequency component decay time constant */
679  REAL8 *gltd = XLALCalloc( glnum, sizeof( REAL8 ) ); /* initialise to zeros */
680  if ( PulsarCheckParam( params, "GLTD" ) ) {
681  const REAL8Vector *tmpvec = PulsarGetREAL8VectorParam( params, "GLTD" );
682  memcpy( gltd, tmpvec->data, tmpvec->length * sizeof( REAL8 ) );
683  }
684 
685  for ( i = 0; i < length; i++ ) {
686  glphase->data[i] = 0.;
687  tdt = XLALGPSGetREAL8( &datatimes->data[i] ) + ssbdts->data[i];
688  if ( bsbdts != NULL ) {
689  tdt += bsbdts->data[i];
690  }
691  for ( UINT4 k = 0; k < glnum; k++ ) {
692  if ( tdt >= glep->data[k] ) {
693  REAL8 dtg = 0, expd = 1.;
694  dtg = tdt - glep->data[k]; /* time since glitch */
695  if ( gltd[k] != 0. ) {
696  expd = exp( -dtg / gltd[k] ); /* decaying part of glitch */
697  }
698  glphase->data[i] += glph[k] + glf0[k] * dtg + 0.5 * glf1[k] * dtg * dtg + ( 1. / 6. ) * glf2[k] * dtg * dtg * dtg + glf0d[k] * gltd[k] * ( 1. - expd );
699  }
700  }
701  }
702 
703  XLALFree( glph );
704  XLALFree( glf0 );
705  XLALFree( glf1 );
706  XLALFree( glf2 );
707  XLALFree( glf0d );
708  XLALFree( gltd );
709  }
710 
711  return glphase;
712 }
713 
714 
715 /**
716  * \brief Computes the phase evolution due to the presence of FITWAVES parameters
717  *
718  * This function calculates the phase due to the presence on FITWAVES parameters in
719  * the pulsar timing model. These are used to fit multiple sinusoids to account for
720  * strong red noise effects (e.g., timing noise) in the pulsar model.
721  *
722  * \param params [in] A set of pulsar parameters
723  * \param datatimes [in] A vector of GPS times at Earth
724  * \param ssbdts [in] A vector of solar system barycentre time delays
725  * \param freq [in] The EM frequency.
726  *
727  * \return A vector of (EM) phases in cycles
728  */
730  const LIGOTimeGPSVector *datatimes,
731  const REAL8Vector *ssbdts,
732  REAL8 freq )
733 {
734  /* check inputs */
735  XLAL_CHECK_NULL( params != NULL, XLAL_EFUNC, "PulsarParameters must not be NULL" );
736  XLAL_CHECK_NULL( datatimes != NULL, XLAL_EFUNC, "datatimes must not be NULL" );
737  XLAL_CHECK_NULL( ssbdts != NULL, XLAL_EFUNC, "ssbdts must not be NULL" );
738  XLAL_CHECK_NULL( ssbdts->length == datatimes->length, XLAL_EFUNC, "datatimes and ssbdts must be the same length" );
739  XLAL_CHECK_NULL( freq > 0.0, XLAL_EFUNC, "Frequency must be positive" );
740 
741  UINT4 i = 0, length = 0, j = 0;
742  REAL8Vector *phasewave = NULL;
743 
744  length = datatimes->length;
745 
746  /* allocate memory for phases */
747  phasewave = XLALCreateREAL8Vector( length );
748  memset( phasewave->data, 0, phasewave->length * sizeof( REAL8 ) ); // set to zeros
749 
750  /* get FITWAVES parameters */
751  if ( PulsarCheckParam( params, "WAVESIN" ) && PulsarCheckParam( params, "WAVECOS" ) ) {
752  const REAL8Vector *wsin = PulsarGetREAL8VectorParam( params, "WAVESIN" );
753  const REAL8Vector *wcos = PulsarGetREAL8VectorParam( params, "WAVECOS" );
754 
755  XLAL_CHECK_NULL( wsin->length == wcos->length, XLAL_EFUNC, "Lengths of FITWAVES sin and cos parameters are not the same" );
756  UINT4 nwaves = wsin->length;
757 
758  REAL8 waveepoch = PulsarGetREAL8ParamOrZero( params, "WAVEEPOCH" );
759  REAL8 waveom = PulsarGetREAL8ParamOrZero( params, "WAVE_OM" );
760 
761  REAL8 twave = 0., dtwave = 0.;
762  for ( i = 0; i < length; i++ ) {
763  twave = 0.0;
764  /* note: this does not include the binary times delays */
765  dtwave = ( XLALGPSGetREAL8( &datatimes->data[i] ) + ssbdts->data[i] - waveepoch ) / 86400.; /* in days */
766 
767  for ( j = 0; j < nwaves; j++ ) {
768  twave += wsin->data[j] * sin( waveom * ( REAL8 )( j + 1. ) * dtwave );
769  twave += wcos->data[j] * cos( waveom * ( REAL8 )( j + 1. ) * dtwave );
770  }
771 
772  phasewave->data[i] = freq * twave;
773  }
774  }
775 
776  return phasewave;
777 }
778 
779 
780 /**
781  * \brief The amplitude model of a complex heterodyned signal from the
782  * \f$ l=2, m=1,2 \f$ harmonics of a rotating neutron star.
783  *
784  * This function calculates the complex heterodyned time series model for a
785  * rotating neutron star. It will currently calculate the model for emission
786  * from the \f$ l=m=2 \f$ harmonic (which gives emission at twice the rotation
787  * frequency) and/or the \f$ l=2 \f$ and \f$ m=1 \f$ harmonic (which gives emission
788  * at the rotation frequency). See LIGO T1200265-v3. Further harmonics can be
789  * added and are defined by the \c freqFactor value, which is the multiple of
790  * the spin-frequency at which emission is produced.
791  *
792  * The antenna pattern functions are contained in a 1D lookup table, so within
793  * this function the correct value for the given time is interpolated from this
794  * lookup table using linear interpolation.
795  *
796  * \param pars [in] A set of pulsar parameters
797  * \param freqfactor [in] The harmonic frequency of the signal in units of the
798  * pulsar rotation frequency
799  * \param varyphase [in] Set to a non-zero value is the signal phase is
800  * different to the heterodyne phase (or if wanting the signal output at all
801  * time stamps).
802  * \param useroq [in] Set to a non-zero value if a reduced order quadrature
803  * likelihood is being used
804  * \param nonGR [in] Set to a non-zero value to indicate a non-GR polarisation
805  * is used
806  * \param timestamps [in] A vector of GPS times at which to calculate the signal
807  * \param resp [in] A detector response function look-up table
808  *
809  * \return A \c COMPLEX16TimeSeries the amplitude time series
810  */
812  REAL8 freqfactor,
813  UINT4 varyphase,
814  UINT4 useroq,
815  UINT4 nonGR,
817  const DetResponseTimeLookupTable *resp )
818 {
819  COMPLEX16TimeSeries *csignal = NULL;
820 
821  /* create signal if not already allocated */
822  LIGOTimeGPS gpstime; /* dummy time stamp */
823  gpstime.gpsSeconds = 0;
824  gpstime.gpsNanoSeconds = 0;
825 
826  /* check for transient signal */
827  INT4 rectWindow = 0, expWindow = 0;
828  REAL8 transientStartTime = PulsarGetREAL8ParamOrZero( pars, "TRANSIENTSTARTTIME" );
829  REAL8 transientTau = PulsarGetREAL8ParamOrZero( pars, "TRANSIENTTAU" );
830 
831  if ( PulsarCheckParam( pars, "TRANSIENTWINDOWTYPE" ) ) {
832  const CHAR *transientWindow = PulsarGetStringParam( pars, "TRANSIENTWINDOWTYPE" );
833  rectWindow = !strcmp( transientWindow, "RECT" );
834  expWindow = !strcmp( transientWindow, "EXP" );
835  }
836 
837  if ( varyphase || useroq || rectWindow || expWindow ) {
838  XLAL_CHECK_NULL( timestamps->length > 0, XLAL_EFUNC, "length must be a positive integer" );
839 
840  /* in these cases use signal length to specify the length of the signal */
842  } else {
843  if ( nonGR ) {
844  /* for non-GR signals there are six values that need to be held */
845  csignal = XLALCreateCOMPLEX16TimeSeries( "", &gpstime, 0., 1., &lalSecondUnit, 6 );
846  } else {
847  /* for GR signals just two values are required */
848  csignal = XLALCreateCOMPLEX16TimeSeries( "", &gpstime, 0., 1., &lalSecondUnit, 2 );
849  }
850  }
851 
852  /* switch to waveform parameters if required */
854 
855  /* check inputs */
856  XLAL_CHECK_NULL( pars != NULL, XLAL_EFUNC, "PulsarParameters is NULL" );
857  XLAL_CHECK_NULL( freqfactor > 0., XLAL_EFUNC, "freqfactor must be a positive number" );
858  XLAL_CHECK_NULL( resp != NULL, XLAL_EFUNC, "Response look-up table is NULL" );
859  XLAL_CHECK_NULL( freqfactor != 1. || nonGR != 1, XLAL_EFUNC, "A non-GR model is not defined for a frequency harmonic of 1" );
860 
861  UINT4 i = 0;
862 
863  REAL8 T, twopsi, t0;
864  REAL8 cosiota = 0.;
865  if ( PulsarCheckParam( pars, "IOTA" ) ) {
866  /* use IOTA if present */
867  cosiota = cos( PulsarGetREAL8Param( pars, "IOTA" ) );
868  } else {
869  cosiota = PulsarGetREAL8ParamOrZero( pars, "COSIOTA" );
870  }
871  REAL8 siniota = sin( acos( cosiota ) );
872  REAL8 s2psi = 0., c2psi = 0., spsi = 0., cpsi = 0.;
873 
874  twopsi = 2.*PulsarGetREAL8ParamOrZero( pars, "PSI" );
875  s2psi = sin( twopsi );
876  c2psi = cos( twopsi );
877 
878  t0 = XLALGPSGetREAL8( &resp->t0 ); /* epoch of detector response look-up table */
879 
880  if ( nonGR == 1 ) {
881  spsi = sin( PulsarGetREAL8ParamOrZero( pars, "PSI" ) );
882  cpsi = cos( PulsarGetREAL8ParamOrZero( pars, "PSI" ) );
883  }
884 
885  COMPLEX16 expPhi;
886  COMPLEX16 Cplus = 0., Ccross = 0., Cx = 0., Cy = 0., Cl = 0., Cb = 0.;
887 
888  /* get the amplitude and phase factors */
889  if ( freqfactor == 1. ) {
890  /* the l=2, m=1 harmonic at the rotation frequency. */
891  if ( nonGR ) { /* amplitude if nonGR is specified */
892  COMPLEX16 expPhiTensor, expPsiTensor, expPhiScalar, expPsiScalar, expPhiVector, expPsiVector;
893 
894  expPhiTensor = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PHI0TENSOR_F" ) );
895  expPsiTensor = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PSITENSOR_F" ) );
896  expPhiScalar = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PHI0SCALAR_F" ) );
897  expPsiScalar = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PSISCALAR_F" ) );
898  expPhiVector = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PHI0VECTOR_F" ) );
899  expPsiVector = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PSIVECTOR_F" ) );
900 
901  Cplus = 0.5 * expPhiTensor * PulsarGetREAL8ParamOrZero( pars, "HPLUS_F" );
902  Ccross = 0.5 * expPhiTensor * PulsarGetREAL8ParamOrZero( pars, "HCROSS_F" ) * expPsiTensor;
903  Cx = 0.5 * expPhiVector * PulsarGetREAL8ParamOrZero( pars, "HVECTORX_F" );
904  Cy = 0.5 * expPhiVector * PulsarGetREAL8ParamOrZero( pars, "HVECTORY_F" ) * expPsiVector;
905  Cb = 0.5 * expPhiScalar * PulsarGetREAL8ParamOrZero( pars, "HSCALARB_F" );
906  Cl = 0.5 * expPhiScalar * PulsarGetREAL8ParamOrZero( pars, "HSCALARL_F" ) * expPsiScalar;
907  } else {
908  expPhi = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PHI21" ) );
909  Cplus = -0.25 * PulsarGetREAL8ParamOrZero( pars, "C21" ) * siniota * cosiota * expPhi;
910  Ccross = 0.25 * I * PulsarGetREAL8ParamOrZero( pars, "C21" ) * siniota * expPhi;
911  }
912  } else if ( freqfactor == 2. ) {
913  /* the l=2, m=2 harmonic at twice the rotation frequency */
914  if ( nonGR ) { /* amplitude if nonGR is specified */
915  COMPLEX16 expPhiTensor, expPsiTensor, expPhiScalar, expPsiScalar, expPhiVector, expPsiVector;
916 
917  expPhiTensor = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PHI0TENSOR" ) );
918  expPsiTensor = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PSITENSOR" ) );
919  expPhiScalar = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PHI0SCALAR" ) );
920  expPsiScalar = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PSISCALAR" ) );
921  expPhiVector = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PHI0VECTOR" ) );
922  expPsiVector = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PSIVECTOR" ) );
923 
924  Cplus = 0.5 * expPhiTensor * PulsarGetREAL8ParamOrZero( pars, "HPLUS" );
925  Ccross = 0.5 * expPhiTensor * PulsarGetREAL8ParamOrZero( pars, "HCROSS" ) * expPsiTensor;
926  Cx = 0.5 * expPhiVector * PulsarGetREAL8ParamOrZero( pars, "HVECTORX" );
927  Cy = 0.5 * expPhiVector * PulsarGetREAL8ParamOrZero( pars, "HVECTORY" ) * expPsiVector;
928  Cb = 0.5 * expPhiScalar * PulsarGetREAL8ParamOrZero( pars, "HSCALARB" );
929  Cl = 0.5 * expPhiScalar * PulsarGetREAL8ParamOrZero( pars, "HSCALARL" ) * expPsiScalar;
930  } else { /* just GR tensor mode amplitudes */
931  expPhi = cexp( I * PulsarGetREAL8ParamOrZero( pars, "PHI22" ) );
932  Cplus = -0.5 * PulsarGetREAL8ParamOrZero( pars, "C22" ) * ( 1. + cosiota * cosiota ) * expPhi;
933  Ccross = I * PulsarGetREAL8ParamOrZero( pars, "C22" ) * cosiota * expPhi;
934  }
935  } else {
936  XLAL_ERROR_NULL( XLAL_EINVAL, "Error... currently unknown frequency factor (%.2lf) for models.", freqfactor );
937  }
938 
939  if ( varyphase || useroq || rectWindow || expWindow ) { /* have to compute the full time domain signal */
940  REAL8 tsv;
941 
942  /* set lookup table parameters */
943  tsv = LAL_DAYSID_SI / ( REAL8 )resp->ntimebins;
944 
945  for ( i = 0; i < csignal->data->length; i++ ) {
946  REAL8 plus00, plus01, cross00, cross01, plus = 0., cross = 0.;
947  REAL8 x00, x01, y00, y01, b00, b01, l00, l01;
948  REAL8 timeGPS, timeScaled, timeMin, timeMax;
949  REAL8 plusT = 0., crossT = 0., x = 0., y = 0., xT = 0., yT = 0., b = 0., l = 0.;
950  INT4 timebinMin, timebinMax;
951 
952  /* set the time bin for the lookup table */
953  /* sidereal day in secs*/
954  timeGPS = XLALGPSGetREAL8( &timestamps->data[i] );
955  T = fmod( timeGPS - t0, LAL_DAYSID_SI ); /* convert GPS time to sidereal day */
956 
957  /* set signal to zero for transient signals as required */
958  if ( rectWindow && ( timeGPS < transientStartTime || timeGPS > transientStartTime + transientTau ) ) {
959  csignal->data->data[i] = 0.0 + I * 0.0;
960  continue;
961  } else if ( expWindow && timeGPS < transientStartTime ) {
962  csignal->data->data[i] = 0.0 + I * 0.0;
963  continue;
964  }
965 
966  timebinMin = ( INT4 )fmod( floor( T / tsv ), resp->ntimebins );
967  timeMin = timebinMin * tsv;
968  timebinMax = ( INT4 )fmod( timebinMin + 1, resp->ntimebins );
969  timeMax = timeMin + tsv;
970 
971  /* get values of matrix for linear interpolation */
972  plus00 = resp->fplus->data[timebinMin];
973  plus01 = resp->fplus->data[timebinMax];
974 
975  cross00 = resp->fcross->data[timebinMin];
976  cross01 = resp->fcross->data[timebinMax];
977 
978  /* rescale time for linear interpolation on a unit square */
979  timeScaled = ( T - timeMin ) / ( timeMax - timeMin );
980 
981  plus = plus00 + ( plus01 - plus00 ) * timeScaled;
982  cross = cross00 + ( cross01 - cross00 ) * timeScaled;
983 
984  plusT = plus * c2psi + cross * s2psi;
985  crossT = cross * c2psi - plus * s2psi;
986 
987  if ( nonGR ) {
988  x00 = resp->fx->data[timebinMin];
989  x01 = resp->fx->data[timebinMax];
990  y00 = resp->fy->data[timebinMin];
991  y01 = resp->fy->data[timebinMax];
992  b00 = resp->fb->data[timebinMin];
993  b01 = resp->fb->data[timebinMax];
994  l00 = resp->fl->data[timebinMin];
995  l01 = resp->fl->data[timebinMax];
996 
997  x = x00 + ( x01 - x00 ) * timeScaled;
998  y = y00 + ( y01 - y00 ) * timeScaled;
999  b = b00 + ( b01 - b00 ) * timeScaled;
1000  l = l00 + ( l01 - l00 ) * timeScaled;
1001 
1002  xT = x * cpsi + y * spsi;
1003  yT = y * cpsi - x * spsi;
1004  }
1005 
1006  /* create the complex signal amplitude model appropriate for the harmonic */
1007  csignal->data->data[i] = ( Cplus * plusT ) + ( Ccross * crossT );
1008 
1009  /* add non-GR components if required */
1010  if ( nonGR ) {
1011  csignal->data->data[i] += ( Cx * xT ) + ( Cy * yT ) + Cb * b + Cl * l;
1012  }
1013 
1014  /* add exponential window if required */
1015  if ( expWindow ) {
1016  csignal->data->data[i] *= exp( -( timeGPS - transientStartTime ) / transientTau );
1017  }
1018  }
1019  } else { /* just have to calculate the values to multiply the pre-summed data */
1020  /* for tensor-only models (e.g. the default of GR) calculate the two components of
1021  * the single model value - things multiplied by a(t) and things multiplied by b(t)
1022  * (both these will have real and imaginary components). NOTE: the values input into
1023  * csignal->data->data are not supposed to be identical to the above
1024  * relationships between the amplitudes and polarisation angles, as these are the
1025  * multiplicative coefficients of the a(t) and b(t) summations.
1026  */
1027 
1028  /* put multiples of a(t) in first value and b(t) in second */
1029  if ( !nonGR ) {
1030  csignal->data->data[0] = ( Cplus * c2psi - Ccross * s2psi );
1031  csignal->data->data[1] = ( Cplus * s2psi + Ccross * c2psi );
1032  } else {
1033  csignal->data->data[0] = ( Cplus * c2psi - Ccross * s2psi );
1034  csignal->data->data[1] = ( Cplus * s2psi + Ccross * c2psi );
1035  csignal->data->data[2] = ( Cx * cpsi - Cy * spsi );
1036  csignal->data->data[3] = ( Cx * spsi + Cy * cpsi );
1037  csignal->data->data[4] = Cb;
1038  csignal->data->data[5] = Cl;
1039  }
1040  }
1041 
1042  return csignal;
1043 }
1044 
1045 
1046 /**
1047  * \brief Generate the model of the neutron star signal
1048  *
1049  * Firstly the time varying amplitude of the signal will be calculated based
1050  * on the antenna pattern and amplitude parameters. Then, if searching over
1051  * phase parameters, the phase evolution of the signal will be calculated. The
1052  * difference between the new phase model, \f$ \phi(t)_n \f$ , and that used to
1053  * heterodyne the data, \f$ \phi(t)_h \f$ , will be calculated and the complex
1054  * signal model, \f$ M \f$ , modified accordingly:
1055  * \f[
1056  * M'(t) = M(t)\exp{i((\phi(t)_n - \phi(t)_h))}.
1057  * \f]
1058  * This does not try to undo the signal modulation in the data, but instead
1059  * replicates the modulation in the model, hence the positive phase difference
1060  * rather than a negative phase in the exponential function.
1061  *
1062  * The model is described in Equations 7 and 8 of \cite Pitkin2017 .
1063  *
1064  * \param pars [in] A \c PulsarParameters structure containing the model parameters
1065  * \param origpars [in] A \c PulsarParameters structure containing the original heterodyne parameters
1066  * \param freqfactor [in] The harmonic frequency of the signal in units of the
1067  * pulsar rotation frequency
1068  * \param usephase [in] Set to a non-zero value is the signal phase is
1069  * different to the heterodyne phase (or if wanting the signal output at all
1070  * time stamps).
1071  * \param useroq [in] Set to a non-zero value if a reduced order quadrature
1072  * likelihood is being used
1073  * \param nonGR [in] Set to a non-zero value to indicate a non-GR polarisation
1074  * is used
1075  * \param timestamps [in] A vector of GPS times at which to calculate the signal
1076  * \param hetssbdelays [in] The vector of SSB time delays used for the original heterodyne. If this is
1077  * \c NULL then the SSB delay for the given position will be calculated.
1078  * \param calcSSBDelay [in] Set to a non-zero value if the SSB delay needs to be recalculated at
1079  * an updated sky position compared to that used for the heterodyne.
1080  * \param hetbsbdelays [in] The vector of BSB time delays used for the original heterodyne. If this is
1081  * \c NULL then the BSB delay for the given binary parameters will be calculated.
1082  * \param calcBSBDelay [in] Set to a non-zero value if the BSB delay needs to be calulated at
1083  * a set of updated binary system parameters.
1084  * \param glphase [in] The vector containing the glitch phase evolution used for the original heterodyne.
1085  * If this is \c NULL then the glitch phase for the given glitch parameters will be calculated.
1086  * \param calcglphase [in] Set to a non-zero value if the glitch phase needs to be calulated at
1087  * a set of updated glitch parameters.
1088  * \param fitwavesphase [in] The vector of FITWAVES phases used for the original heterodyne. If this is
1089  * \c NULL then the FITWAVES phase for the given FITWAVES parameters will be calculated.
1090  * \param calcfitwaves [in] Set to a non-zero value if the FITWAVES phase needs to be calulated at
1091  * a set of updated FITWAVES parameters.
1092  * \param resp [in] A loop-up table for the detector response function.
1093  * \param ephem [in] A pointer to an \c EphemerisData structure containing solar system ephemeris information
1094  * \param tdat [in] A pointer to a \c TimeCorrectionData structure containing time system correction information
1095  * \param ttype [in] The \c TimeCorrectionType value
1096  *
1097  * \sa XLALHeterodynedPulsarGetAmplitudeModel
1098  * \sa XLALHeterodynedPulsarGetPhaseModel
1099  */
1101  PulsarParameters *origpars,
1102  REAL8 freqfactor,
1103  UINT4 usephase,
1104  UINT4 useroq,
1105  UINT4 nonGR,
1107  REAL8Vector *hetssbdelays,
1108  UINT4 calcSSBDelay,
1109  REAL8Vector *hetbsbdelays,
1110  UINT4 calcBSBDelay,
1111  REAL8Vector *glphase,
1112  UINT4 calcglphase,
1113  REAL8Vector *fitwavesphase,
1114  UINT4 calcfitwaves,
1115  const DetResponseTimeLookupTable *resp,
1116  const EphemerisData *ephem,
1117  const TimeCorrectionData *tdat,
1118  TimeCorrectionType ttype )
1119 {
1120  UINT4 i = 0;
1121  COMPLEX16TimeSeries *csignal = NULL;
1122 
1123  /* get amplitude model */
1125  freqfactor,
1126  usephase,
1127  useroq,
1128  nonGR,
1129  timestamps,
1130  resp );
1131 
1132  // include phase change if required
1133  if ( usephase ) {
1134  REAL8Vector *dphi = NULL;
1136  origpars,
1137  timestamps,
1138  freqfactor,
1139  hetssbdelays,
1140  calcSSBDelay,
1141  hetbsbdelays,
1142  calcBSBDelay,
1143  glphase,
1144  calcglphase,
1145  fitwavesphase,
1146  calcfitwaves,
1147  resp->det,
1148  ephem,
1149  tdat,
1150  ttype );
1151 
1152  COMPLEX16 M = 0., expp = 0.;
1153 
1154  for ( i = 0; i < dphi->length; i++ ) {
1155  /* phase factor by which to multiply the (almost) DC signal model. NOTE: this does not try to undo
1156  * the signal modulation in the data, but instead replicates it in the model, hence the positive
1157  * phase rather than a negative phase in the cexp function. */
1158  expp = cexp( LAL_TWOPI * I * dphi->data[i] );
1159 
1160  M = csignal->data->data[i];
1161 
1162  /* heterodyne */
1163  csignal->data->data[i] = M * expp;
1164  }
1165 
1166  XLALDestroyREAL8Vector( dphi );
1167  }
1168 
1169  return csignal;
1170 }
1171 
1172 
1173 /**
1174  * \brief Creates a lookup table of the detector antenna pattern
1175  *
1176  * This function creates a lookup table of the tensor, vector and scalar
1177  * antenna patterns for a given detector orientation and source sky position.
1178  * For the tensor modes these are the functions given by equations 10-13 in
1179  * \cite JKS98 , whilst for the vector and scalar modes they are the \f$ \psi \f$
1180  * independent parts of e.g. equations 5-8 of \cite Nishizawa2009 . We remove
1181  * the \f$ \psi \f$ dependance by setting \f$ \psi=0 \f$ .
1182  *
1183  * If \c avedt is a value over 60 seconds then the antenna pattern will
1184  * actually be the mean value from 60 second intervals within that timespan.
1185  * This accounts for the fact that each data point is actually an averaged
1186  * value over the given timespan.
1187  *
1188  * \param t0 [in] initial GPS time of the data
1189  * \param det [in] structure containing the detector
1190  * \param alpha [in] the source right ascension in radians
1191  * \param delta [in] the source declination in radians
1192  * \param timeSteps [in] the number of grid bins to use in time
1193  * \param avedt [in] average the antenna pattern over this timespan
1194  */
1196  const LALDetector *det,
1197  REAL8 alpha,
1198  REAL8 delta,
1199  UINT4 timeSteps,
1200  REAL8 avedt )
1201 {
1202  LIGOTimeGPS gps;
1203 
1204  // allocate structure
1206  resp = XLALMalloc( sizeof( *resp ) );
1207  resp->det = XLALMalloc( sizeof( LALDetector * ) );
1208  memcpy( &resp->det, &det, sizeof( det ) );
1209  resp->alpha = alpha;
1210  resp->delta = delta;
1211  resp->psi = 0.;
1212  resp->ntimebins = timeSteps;
1213  resp->fplus = XLALCreateREAL8Vector( timeSteps );
1214  resp->fcross = XLALCreateREAL8Vector( timeSteps );
1215  resp->fx = XLALCreateREAL8Vector( timeSteps );
1216  resp->fy = XLALCreateREAL8Vector( timeSteps );
1217  resp->fb = XLALCreateREAL8Vector( timeSteps );
1218  resp->fl = XLALCreateREAL8Vector( timeSteps );
1219  XLALGPSSetREAL8( &resp->t0, t0 ); // set the epoch
1220 
1221  REAL8 T = 0., Tstart = 0., Tav = 0., psi = 0.;
1222 
1223  REAL8 fplus = 0., fcross = 0., fx = 0., fy = 0., fb = 0., fl = 0.;
1224  REAL8 tsteps = ( REAL8 )timeSteps;
1225 
1226  UINT4 j = 0, k = 0, nav = 0;
1227 
1228  /* number of points to average */
1229  if ( avedt == 60. ) {
1230  nav = 1;
1231  } else {
1232  nav = floor( avedt / 60. ) + 1;
1233  }
1234 
1235  for ( j = 0 ; j < timeSteps ; j++ ) {
1236  resp->fplus->data[j] = 0.;
1237  resp->fcross->data[j] = 0.;
1238  resp->fx->data[j] = 0.;
1239  resp->fy->data[j] = 0.;
1240  resp->fb->data[j] = 0.;
1241  resp->fl->data[j] = 0.;
1242 
1243  /* central time of lookup table point */
1244  T = t0 + ( REAL8 )j * LAL_DAYSID_SI / tsteps;
1245 
1246  if ( nav % 2 ) { /* is odd */
1247  Tstart = T - 0.5 * ( ( REAL8 )nav - 1. ) * 60.;
1248  } else { /* is even */
1249  Tstart = T - ( 0.5 * ( REAL8 )nav - 1. ) * 60. - 30.;
1250  }
1251 
1252  for ( k = 0; k < nav; k++ ) {
1253  Tav = Tstart + 60.*( REAL8 )k;
1254 
1255  XLALGPSSetREAL8( &gps, Tav );
1256  XLALComputeDetAMResponseExtraModes( &fplus, &fcross, &fb, &fl, &fx, &fy, det->response,
1257  alpha, delta, psi,
1259 
1260  resp->fplus->data[j] += fplus;
1261  resp->fcross->data[j] += fcross;
1262  resp->fx->data[j] += fx;
1263  resp->fy->data[j] += fy;
1264  resp->fb->data[j] += fb;
1265  resp->fl->data[j] += fl;
1266  }
1267 
1268  resp->fplus->data[j] /= ( REAL8 )nav;
1269  resp->fcross->data[j] /= ( REAL8 )nav;
1270  resp->fx->data[j] /= ( REAL8 )nav;
1271  resp->fy->data[j] /= ( REAL8 )nav;
1272  resp->fb->data[j] /= ( REAL8 )nav;
1273  resp->fl->data[j] /= ( REAL8 )nav;
1274  }
1275 
1276  return resp;
1277 }
1278 
1279 
1280 /** \brief Free memory for antenna response look-up table structure
1281  *
1282  * \param resp [in] the look-up table structure to be freed
1283  */
1285 {
1286  if ( resp == NULL ) {
1287  return;
1288  }
1289 
1290  if ( resp->fplus ) {
1291  XLALDestroyREAL8Vector( resp->fplus );
1292  }
1293  if ( resp->fcross ) {
1294  XLALDestroyREAL8Vector( resp->fcross );
1295  }
1296  if ( resp->fx ) {
1297  XLALDestroyREAL8Vector( resp->fx );
1298  }
1299  if ( resp->fy ) {
1300  XLALDestroyREAL8Vector( resp->fy );
1301  }
1302  if ( resp->fb ) {
1303  XLALDestroyREAL8Vector( resp->fb );
1304  }
1305  if ( resp->fl ) {
1306  XLALDestroyREAL8Vector( resp->fl );
1307  }
1308 
1309  XLALFree( resp );
1310 }
1311 
1312 
1313 /**
1314  * \brief Convert source parameters into amplitude and phase notation parameters
1315  *
1316  * Convert the physical source parameters into the amplitude and phase notation
1317  * given in Eqns 62-65 of \cite Jones2015 .
1318  *
1319  * Note that \c phi0 is essentially the rotational phase of the pulsar. Also,
1320  * note that if using \f$ h_0 \f$ , and therefore the convention for a signal as
1321  * defined in \cite JKS98 , the sign of the waveform model is the opposite of
1322  * that in \cite Jones2015 , and therefore a sign flip is required in the
1323  * amplitudes.
1324  */
1326 {
1327  REAL8 sinlambda, coslambda, sinlambda2, coslambda2, sin2lambda;
1328  REAL8 theta, sintheta, costheta2, sintheta2, sin2theta;
1331  REAL8 I21 = PulsarGetREAL8ParamOrZero( params, "I21" );
1332  REAL8 I31 = PulsarGetREAL8ParamOrZero( params, "I31" );
1333  REAL8 C21 = PulsarGetREAL8ParamOrZero( params, "C21" );
1334  REAL8 C22 = PulsarGetREAL8ParamOrZero( params, "C22" );
1335  REAL8 phi21 = PulsarGetREAL8ParamOrZero( params, "PHI21" );
1336  REAL8 phi22 = PulsarGetREAL8ParamOrZero( params, "PHI22" );
1337  REAL8 lambda = PulsarGetREAL8ParamOrZero( params, "LAMBDAPIN" );
1339  REAL8 q22 = PulsarGetREAL8ParamOrZero( params, "Q22" );
1340 
1341  REAL8 dist = 0.; /* distance in metres */
1342  /* set distance (a DIST param takes precedence over PX) */
1343  if ( PulsarCheckParam( params, "DIST" ) ) {
1344  dist = PulsarGetREAL8Param( params, "DIST" );
1345  } else if ( PulsarCheckParam( params, "PX" ) ) {
1347  }
1348 
1349  if ( ( q22 != 0. && dist != 0. ) && ( I21 == 0. && I21 == 0. && C21 == 0. && C22 == 0. ) ) {
1350  /* convert mass quadrupole to C22 parameter */
1351  if ( !PulsarCheckParam( params, "F" ) ) {
1352  XLAL_ERROR_VOID( XLAL_EINVAL, "Error... not frequency values given" );
1353  }
1354 
1356  if ( f0 == 0. ) {
1357  XLAL_ERROR_VOID( XLAL_EINVAL, "Error... frequency is zero" );
1358  }
1359 
1360  /* convert q22 to h0 */
1361  h0 = q22 * sqrt( 8. * LAL_PI / 15. ) * 16. * LAL_PI * LAL_PI * LAL_G_SI * f0 * f0 / ( LAL_C_SI * LAL_C_SI * LAL_C_SI * LAL_C_SI * dist );
1362 
1363  C22 = -0.5 * h0;
1364  PulsarAddParam( params, "C22", &C22, PULSARTYPE_REAL8_t );
1365 
1366  if ( phi22 == 0. ) {
1367  phi22 = 2.*phi0;
1368  phi22 = phi22 - LAL_TWOPI * floor( phi22 / LAL_TWOPI );
1369  PulsarAddParam( params, "PHI22", &phi22, PULSARTYPE_REAL8_t );
1370  }
1371  } else if ( h0 != 0. ) {
1372  C22 = -0.5 * h0; /* note the change in sign so that the triaxial model conforms to the convertion in JKS98 */
1373  PulsarAddParam( params, "C22", &C22, PULSARTYPE_REAL8_t );
1374 
1375  if ( phi22 == 0. ) {
1376  phi22 = 2.*phi0;
1377  phi22 = phi22 - LAL_TWOPI * floor( phi22 / LAL_TWOPI );
1378  PulsarAddParam( params, "PHI22", &phi22, PULSARTYPE_REAL8_t );
1379  }
1380  } else if ( ( I21 != 0. || I31 != 0. ) && ( C22 == 0. && C21 == 0. ) ) {
1381  sinlambda = sin( lambda );
1382  coslambda = cos( lambda );
1383  sin2lambda = sin( 2. * lambda );
1384  sinlambda2 = SQUARE( sinlambda );
1385  coslambda2 = SQUARE( coslambda );
1386 
1387  theta = acos( costheta );
1388  sintheta = sin( theta );
1389  sin2theta = sin( 2. * theta );
1390  sintheta2 = SQUARE( sintheta );
1391  costheta2 = SQUARE( costheta );
1392 
1393  REAL8 A22 = I21 * ( sinlambda2 - coslambda2 * costheta2 ) - I31 * sintheta2;
1394  REAL8 B22 = I21 * sin2lambda * costheta;
1395  REAL8 A222 = SQUARE( A22 );
1396  REAL8 B222 = SQUARE( B22 );
1397 
1398  REAL8 A21 = I21 * sin2lambda * sintheta;
1399  REAL8 B21 = sin2theta * ( I21 * coslambda2 - I31 );
1400  REAL8 A212 = SQUARE( A21 );
1401  REAL8 B212 = SQUARE( B21 );
1402 
1403  C22 = 2.*sqrt( A222 + B222 );
1404  C21 = 2.*sqrt( A212 + B212 );
1405 
1406  PulsarAddParam( params, "C22", &C22, PULSARTYPE_REAL8_t );
1407  PulsarAddParam( params, "C21", &C21, PULSARTYPE_REAL8_t );
1408 
1409  phi22 = fmod( 2.*phi0 - atan2( B22, A22 ), LAL_TWOPI );
1410  phi21 = fmod( phi0 - atan2( B21, A21 ), LAL_TWOPI );
1411 
1412  PulsarAddParam( params, "PHI22", &phi22, PULSARTYPE_REAL8_t );
1413  PulsarAddParam( params, "PHI21", &phi21, PULSARTYPE_REAL8_t );
1414  }
1415 }
void XLALBinaryPulsarDeltaTNew(BinaryPulsarOutput *output, BinaryPulsarInput *input, PulsarParameters *params)
function to calculate the binary system delay using new parameter structure
REAL8Vector * XLALHeterodynedPulsarGetGlitchPhase(PulsarParameters *params, const LIGOTimeGPSVector *datatimes, const REAL8Vector *ssbdts, const REAL8Vector *bsbdts)
Computes the phase evolution due to the presence of glitches.
REAL8Vector * XLALHeterodynedPulsarGetSSBDelay(PulsarParameters *pars, const LIGOTimeGPSVector *datatimes, const LALDetector *detector, const EphemerisData *ephem, const TimeCorrectionData *tdat, TimeCorrectionType ttype)
Computes the delay between a GPS time at Earth and the solar system barycentre.
void XLALPulsarSourceToWaveformParams(PulsarParameters *params)
Convert source parameters into amplitude and phase notation parameters.
void XLALDestroyDetResponseTimeLookupTable(DetResponseTimeLookupTable *resp)
Free memory for antenna response look-up table structure.
COMPLEX16TimeSeries * XLALHeterodynedPulsarGetAmplitudeModel(PulsarParameters *pars, REAL8 freqfactor, UINT4 varyphase, UINT4 useroq, UINT4 nonGR, const LIGOTimeGPSVector *timestamps, const DetResponseTimeLookupTable *resp)
The amplitude model of a complex heterodyned signal from the harmonics of a rotating neutron star.
#define SQUARE(x)
Macro to square a value.
REAL8Vector * XLALHeterodynedPulsarPhaseDifference(PulsarParameters *params, PulsarParameters *origparams, const LIGOTimeGPSVector *datatimes, REAL8 freqfactor, REAL8Vector *ssbdts, UINT4 calcSSBDelay, REAL8Vector *bsbdts, UINT4 calcBSBDelay, REAL8Vector *glphase, UINT4 calcglphase, REAL8Vector *fitwavesphase, UINT4 calcfitwaves, const LALDetector *detector, const EphemerisData *ephem, const TimeCorrectionData *tdat, TimeCorrectionType ttype)
The phase evolution difference compared to a heterodyned phase (for a pulsar)
REAL8Vector * XLALHeterodynedPulsarGetFITWAVESPhase(PulsarParameters *params, const LIGOTimeGPSVector *datatimes, const REAL8Vector *ssbdts, REAL8 freq)
Computes the phase evolution due to the presence of FITWAVES parameters.
COMPLEX16TimeSeries * XLALHeterodynedPulsarGetModel(PulsarParameters *pars, PulsarParameters *origpars, REAL8 freqfactor, UINT4 usephase, UINT4 useroq, UINT4 nonGR, const LIGOTimeGPSVector *timestamps, REAL8Vector *hetssbdelays, UINT4 calcSSBDelay, REAL8Vector *hetbsbdelays, UINT4 calcBSBDelay, REAL8Vector *glphase, UINT4 calcglphase, REAL8Vector *fitwavesphase, UINT4 calcfitwaves, const DetResponseTimeLookupTable *resp, const EphemerisData *ephem, const TimeCorrectionData *tdat, TimeCorrectionType ttype)
Generate the model of the neutron star signal.
#define ROUND(x)
Macro to round a value to the nearest integer.
DetResponseTimeLookupTable * XLALDetResponseLookupTable(REAL8 t0, const LALDetector *det, REAL8 alpha, REAL8 delta, UINT4 timeSteps, REAL8 avedt)
Creates a lookup table of the detector antenna pattern.
void XLALGetEarthPosVel(EarthState *earth, const EphemerisData *edat, const LIGOTimeGPS *tGPS)
Get the position and velocity of the Earth at a given time.
REAL8Vector * XLALHeterodynedPulsarGetBSBDelay(PulsarParameters *pars, const LIGOTimeGPSVector *datatimes, const REAL8Vector *dts, const EphemerisData *edat)
Computes the delay between a pulsar in a binary system and the barycentre of the system.
int j
int k
static double double delta
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.
void PulsarAddParam(PulsarParameters *pars, const CHAR *name, void *value, PulsarParamType type)
Add a parameter and value to the PulsarParameters structure.
REAL8 PulsarGetREAL8Param(const PulsarParameters *pars, const CHAR *name)
Return a REAL8 parameter.
REAL8 PulsarGetREAL8VectorParamIndividual(const PulsarParameters *pars, const CHAR *name)
Return an individual REAL8 value from a REAL8Vector parameter.
@ PULSARTYPE_REAL8_t
LIGOTimeGPSVector * timestamps
int l
double theta
const double wcos
const double costheta
void XLALComputeDetAMResponseExtraModes(double *fplus, double *fcross, double *fb, double *fl, double *fx, double *fy, const REAL4 D[3][3], const double ra, const double dec, const double psi, const double gmst)
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...
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
#define LAL_PI_2
#define LAL_DAYSID_SI
#define LAL_PI
#define LAL_TWOPI
#define LAL_G_SI
double complex COMPLEX16
double REAL8
char CHAR
uint32_t UINT4
int32_t INT4
void * XLALCalloc(size_t m, size_t n)
void * XLALMalloc(size_t n)
void XLALFree(void *p)
COMPLEX16TimeSeries * XLALCreateCOMPLEX16TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
const LALUnit lalSecondUnit
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
void XLALDestroyREAL8Vector(REAL8Vector *vector)
#define XLAL_ERROR_VOID(...)
#define XLAL_ERROR_NULL(...)
#define XLAL_CHECK_NULL(assertion,...)
XLAL_SUCCESS
XLAL_EFUNC
XLAL_EDOM
XLAL_EINVAL
REAL8 XLALGreenwichMeanSiderealTime(const LIGOTimeGPS *gpstime)
LIGOTimeGPS * XLALGPSSetREAL8(LIGOTimeGPS *epoch, REAL8 t)
REAL8 XLALGPSGetREAL8(const LIGOTimeGPS *epoch)
int gpstime
Definition: hwinject.c:365
M
list y
T
pos
dist
int T0
double alpha
double t0
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.
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
REAL8 deltaT
deltaT to add to TDB in order to account for binary
COMPLEX16Sequence * data
COMPLEX16 * data
Pulsar signal-generation routines for heterodyned data.
REAL8 alpha
the source right ascension in radians
REAL8Vector * fb
scalar breathing mode polarisation response
REAL8 delta
the source declination in radians
REAL8Vector * fl
scalar longitudinal mode polarisation response
REAL8 psi
the polarisation angle in radians
UINT4 ntimebins
number of time bins in the look-up table
REAL8Vector * fy
vector "y" polarisation response
REAL8Vector * fx
vector "x" polarisation response
REAL8Vector * fcross
tensor cross polarisation response
LIGOTimeGPS t0
GPS time epoch for the look-up table.
REAL8Vector * fplus
tensor plus polarisation response
Basic output structure of LALBarycenterEarth.c.
REAL8 velNow[3]
dimensionless velocity of Earth's center at tgps, extrapolated from JPL DE405 ephemeris
REAL8 posNow[3]
Cartesian coords of Earth's center at tgps, extrapolated from JPL DE405 ephemeris; units= sec.
Basic output structure produced by LALBarycenter.c.
REAL8 deltaT
(TDB) - (GPS)
REAL8 roemer
the Roemer delay
This structure contains all information about the center-of-mass positions of the Earth and Sun,...
REAL4 response[3][3]
REAL8 location[3]
INT4 gpsNanoSeconds
A vector of 'timestamps' of type LIGOTimeGPS.
Definition: SFTfileIO.h:188
LIGOTimeGPS * data
array of timestamps
Definition: SFTfileIO.h:193
UINT4 length
number of timestamps
Definition: SFTfileIO.h:192
The PulsarParameters structure to contain a set of pulsar parameters.
REAL8 * data
This structure will contain a vector of time corrections used during conversion from TT to TDB/TCB/Te...