Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
PulsarSimulateCoherentGW.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007 Jolien Creighton, Reinhard Prix, Stephen Fairhurst, Teviet Creighton
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 <math.h>
21#include <lal/LALStdio.h>
22#include <lal/LALStdlib.h>
23#include <lal/LALError.h>
24#include <lal/DetectorSite.h>
25#include <lal/DetResponse.h>
26#include <lal/AVFactories.h>
27#include <lal/Date.h>
28#include <lal/Units.h>
29#include <lal/TimeDelay.h>
30#include <lal/LALBarycenter.h>
31#include <lal/VectorOps.h>
32#include <lal/PulsarSimulateCoherentGW.h>
33#include <lal/SkyCoordinates.h>
34#include <lal/SinCosLUT.h>
35
36/** \name Error Codes */
37/** @{ */
38#define SIMULATECOHERENTGWH_ENUL 1 /**< Unexpected null pointer in arguments */
39#define SIMULATECOHERENTGWH_EBAD 2 /**< A sampling interval is (effectively) zero */
40#define SIMULATECOHERENTGWH_ESIG 3 /**< Input signal must specify amplitude and phase functions */
41#define SIMULATECOHERENTGWH_EDIM 4 /**< Amplitude must be a 2-dimensional vector */
42#define SIMULATECOHERENTGWH_EMEM 5 /**< Memory allocation error */
43#define SIMULATECOHERENTGWH_EUNIT 6 /**< Bad input units */
44/** @} */
45
46/** \cond DONT_DOXYGEN */
47#define SIMULATECOHERENTGWH_MSGENUL "Unexpected null pointer in arguments"
48#define SIMULATECOHERENTGWH_MSGEBAD "A sampling interval is (effectively) zero"
49#define SIMULATECOHERENTGWH_MSGESIG "Input signal must specify amplitude and phase functions"
50#define SIMULATECOHERENTGWH_MSGEDIM "Amplitude must be a 2-dimensional vector"
51#define SIMULATECOHERENTGWH_MSGEMEM "Memory allocation error"
52#define SIMULATECOHERENTGWH_MSGEUNIT "Bad input units"
53/** \endcond */
54
55/**
56 * FIXME: Temporary XLAL-wapper to LAL-function LALPulsarSimulateCoherentGW()
57 *
58 * NOTE: This violates the current version of the XLAL-spec, but is unavoidable at this time,
59 * as LALPulsarSimulateCoherentGW() hasn't been properly XLALified yet, and doing this would be beyond
60 * the scope of this patch.
61 * However, doing it here in this way is better than calling LALxxx() from various
62 * far-flung XLAL-functions, as in this way the "violation" is localized in one place, and serves
63 * as a reminder for future XLAL-ification at the same time.
64 */
65int
66XLALPulsarSimulateCoherentGW( REAL4TimeSeries *output, ///< [in/out] output timeseries
67 PulsarCoherentGW *CWsignal, ///< [in] internal signal representation
68 PulsarDetectorResponse *detector ///< [in] detector response
69 )
70{
71 XLAL_CHECK( output != NULL, XLAL_EINVAL );
72 XLAL_CHECK( CWsignal != NULL, XLAL_EINVAL );
74
76
78
79 XLAL_CHECK( status.statusCode == 0, XLAL_EFAILED, "LALPulsarSimulateCoherentGW() failed with code=%d, msg='%s'\n", status.statusCode, status.statusDescription );
80
81 return XLAL_SUCCESS;
82
83} // XLALPulsarSimulateCoherentGW()
84
85
86
87/* A macro that takes a detector time (in units of output->deltaT from
88 output->epoch) and adds the propagation time interpolated from the
89 delays tabulated in delayData. The following parameters are
90 required to be defined outside the macro, and are set by it:
91
92 REAL4 realIndex; the interpolation point in delayData
93 INT4 intIndex; the index immediately preceding realIndex
94 REAL4 indexFrac; the value realIndex - intIndex */
95#define TCENTRE( time ) \
96 ( \
97 realIndex = delayOff + (time)*delayDt, \
98 intIndex = (INT4)floor( realIndex ), \
99 indexFrac = realIndex - intIndex, \
100 time + indexFrac*delayData[intIndex+1] \
101 + (1.0-indexFrac)*delayData[intIndex] \
102 )
103
104/**
105 * \author Creighton, T. D.
106 *
107 * \brief Computes the response of a detector to a coherent gravitational wave.
108 *
109 * This function takes a quasiperiodic gravitational waveform given in
110 * <tt>*signal</tt>, and estimates the corresponding response of the
111 * detector whose position, orientation, and transfer function are
112 * specified in <tt>*detector</tt>. The result is stored in
113 * <tt>*output</tt>.
114 *
115 * The fields <tt>output->epoch</tt>, <tt>output->deltaT</tt>, and
116 * <tt>output->data</tt> must already be set, in order to specify the time
117 * period and sampling rate for which the response is required. If
118 * <tt>output->f0</tt> is nonzero, idealized heterodyning is performed (an
119 * amount \f$ 2\pi f_0(t-t_0) \f$ is subtracted from the phase before computing
120 * the sinusoid, where \f$ t_0 \f$ is the heterodyning epoch defined in
121 * \c detector). For the input signal, <tt>signal->h</tt> is ignored,
122 * and the signal is treated as zero at any time for which either
123 * <tt>signal->a</tt> or <tt>signal->phi</tt> is not defined.
124 *
125 * This routine will convert <tt>signal->position</tt> to equatorial
126 * coordinates, if necessary.
127 *
128 * ### Algorithm ###
129 *
130 * The routine first accounts for the time delay between the detector and
131 * the solar system barycentre, based on the detector position
132 * information stored in <tt>*detector</tt> and the propagation direction
133 * specified in <tt>*signal</tt>. Values of the propagation delay are
134 * precomuted at fixed intervals and stored in a table, with the
135 * intervals \f$ \Delta T_\mathrm{delay} \f$ chosen such that the value
136 * interpolated from adjacent table entries will never differ from the
137 * true value by more than some timing error \f$ \sigma_T \f$ . This implies
138 * that:
139 * \f[
140 * \Delta T_\mathrm{delay} \leq \sqrt{
141 * \frac{8\sigma_T}{\max\{a/c\}} } \; ,
142 * \f]
143 * where \f$ \max\{a/c\}=1.32\times10^{-10}\mathrm{s}^{-1} \f$ is the maximum
144 * acceleration of an Earth-based detector in the barycentric frame. The
145 * total propagation delay also includes Einstein and Shapiro delay, but
146 * these are more slowly varying and thus do not constrain the table
147 * spacing. At present, a 400s table spacing is hardwired into the code,
148 * implying \f$ \sigma_T\approx3\mu \f$ s, comparable to the stated accuracy of
149 * <tt>LALBarycenter()</tt>.
150 *
151 * Next, the polarization response functions of the detector
152 * \f$ F_{+,\times}(\alpha,\delta) \f$ are computed for every 10 minutes of the
153 * signal's duration, using the position of the source in <tt>*signal</tt>,
154 * the detector information in <tt>*detector</tt>, and the function
155 * <tt>LALComputeDetAMResponseSeries()</tt>. Subsequently, the
156 * polarization functions are estimated for each output sample by
157 * interpolating these precomputed values. This guarantees that the
158 * interpolated value is accurate to \f$ \sim0.1\% \f$ .
159 *
160 * Next, the frequency response of the detector is estimated in the
161 * quasiperiodic limit as follows:
162 * <ul>
163 * <li> At each sample point in <tt>*output</tt>, the propagation delay is
164 * computed and added to the sample time, and the instantaneous
165 * amplitudes \f$ A_1 \f$ , \f$ A_2 \f$ , frequency \f$ f \f$ , phase \f$ \phi \f$ , and polarization
166 * shift \f$ \Phi \f$ are found by interpolating the nearest values in
167 * <tt>signal->a</tt>, <tt>signal->f</tt>, <tt>signal->phi</tt>, and
168 * <tt>signal->shift</tt>, respectively. If <tt>signal->f</tt> is not
169 * defined at that point in time, then \f$ f \f$ is estimated by differencing
170 * the two nearest values of \f$ \phi \f$ , as \f$ f\approx\Delta\phi/2\pi\Delta
171 * t \f$ . If <tt>signal->shift</tt> is not defined, then \f$ \Phi \f$ is treated as
172 * zero.</li>
173 * <li> The complex transfer function of the detector the frequency \f$ f \f$
174 * is found by interpolating <tt>detector->transfer</tt>. The amplitude of
175 * the transfer function is multiplied with \f$ A_1 \f$ and \f$ A_2 \f$ , and the
176 * phase of the transfer function is added to \f$ \phi \f$ ,</li>
177 * <li> The plus and cross contributions \f$ o_+ \f$ , \f$ o_\times \f$ to the
178 * detector output are computed as in \eqref{eq_quasiperiodic_hpluscross}
179 * of \ref PulsarSimulateCoherentGW_h, but
180 * using the response-adjusted amplitudes and phase.</li>
181 * <li> The final detector response \f$ o \f$ is computed as
182 * \f$ o=(o_+F_+)+(o_\times F_\times) \f$ .</li>
183 * </ul>
184 *
185 * ### A note on interpolation: ###
186 *
187 * Much of the computational work in this routine involves interpolating
188 * various time series to find their values at specific output times.
189 * The algorithm is summarized below.
190 *
191 * Let \f$ A_j = A( t_A + j\Delta t_A ) \f$ be a sampled time series, which we
192 * want to resample at new (output) time intervals \f$ t_k = t_0 + k\Delta
193 * t \f$ . We first precompute the following quantities:
194 * \f{eqnarray}{
195 * t_\mathrm{off} & = & \frac{t_0-t_A}{\Delta t_A} \; , \\
196 * dt & = & \frac{\Delta t}{\Delta t_A} \; .
197 * \f}
198 * Then, for each output sample time \f$ t_k \f$ , we compute:
199 * \f{eqnarray}{
200 * t & = & t_\mathrm{off} + k \times dt \; , \\
201 * j & = & \lfloor t \rfloor \; , \\
202 * f & = & t - j \; ,
203 * \f}
204 * where \f$ \lfloor x\rfloor \f$ is the "floor" function; i.e.\ the largest
205 * integer \f$ \leq x \f$ . The time series sampled at the new time is then:
206 * \f[
207 * A(t_k) = f \times A_{j+1} + (1-f) \times A_j \; .
208 * \f]
209 *
210 * ### Notes ###
211 *
212 * The major computational hit in this routine comes from computing the
213 * sine and cosine of the phase angle in
214 * \eqref{eq_quasiperiodic_hpluscross} of
215 * \ref PulsarSimulateCoherentGW_h. For better online performance, these can
216 * be replaced by other (approximate) trig functions. Presently the code
217 * uses the native \c libm functions by default, or the function
218 * <tt>sincosp()</tt> in \c libsunmath \e if this function is
219 * available \e and the constant \c ONLINE is defined.
220 * Differences at the level of 0.01 begin to appear only for phase
221 * arguments greater than \f$ 10^{14} \f$ or so (corresponding to over 500
222 * years between phase epoch and observation time for frequencies of
223 * around 1kHz).
224 *
225 * To activate this feature, be sure that <tt>sunmath.h</tt> and
226 * \c libsunmath are on your system, and add <tt>-DONLINE</tt> to the
227 * <tt>--with-extra-cppflags</tt> configuration argument. In future this
228 * flag may be used to turn on other efficient trig algorithms on other
229 * (non-Solaris) platforms.
230 *
231 */
232void
235 PulsarCoherentGW *CWsignal,
237{
238 INT4 i, n; /* index over output->data, and its final value */
239 INT4 nMax; /* used to store limits on index ranges */
240 INT4 fInit, fFinal; /* index range for which CWsignal->f is defined */
241 INT4 shiftInit, shiftFinal; /* ditto for CWsignal->shift */
242 UINT4 dtDelayBy2; /* delay table half-interval (s) */
243 UINT4 dtPolBy2; /* polarization table half-interval (s) */
244 REAL4 *outData; /* pointer to output data */
245 REAL8 delayMin, delayMax; /* min and max values of time delay */
246 SkyPosition source; /* source sky position */
247 BOOLEAN transfer; /* 1 if transfer function is specified */
248 BOOLEAN fFlag = 0; /* 1 if frequency left detector->transfer range */
249 BOOLEAN pFlag = 0; /* 1 if frequency was estimated from phase */
250
251 /* get delay table and polaristion tables half intervals if defined (>0) in
252 the PulsarCoherentGW structure otherwise default to 400s for dtDelatBy2 and 300s
253 for dtPolBy2 */
254 dtDelayBy2 = CWsignal->dtDelayBy2 > 0 ? CWsignal->dtDelayBy2 : 400;
255 dtPolBy2 = CWsignal->dtPolBy2 > 0 ? CWsignal->dtPolBy2 : 300;
256
257 /* The amplitude, frequency, phase, polarization shift, polarization
258 response, and propagation delay are stored in arrays that must be
259 interpolated. For a quantity x, we define a pointer xData to the
260 data array. At some time t measured in units of output->deltaT,
261 the interpolation point in xData is given by ( xOff + t*xDt ),
262 where xOff is an offset and xDt is a relative sampling rate. */
263 LALDetAMResponseSeries polResponse;
264 REAL8Vector *delay = NULL;
265 REAL4 *aData, *fData, *shiftData, *plusData, *crossData;
266 REAL8 *phiData, *delayData;
267 REAL8 aOff, fOff, phiOff, shiftOff, polOff, delayOff;
268 REAL8 aDt, fDt, phiDt, shiftDt, polDt, delayDt;
269
270 /* Frequencies in the detector transfer function are interpolated
271 similarly, except everything is normalized with respect to
272 detector->transfer->deltaF. */
273 REAL4Vector *aTransfer = NULL;
274 REAL4Vector *phiTransfer = NULL;
275 REAL4Vector *phiTemp = NULL;
276 REAL4 *aTransData = NULL, *phiTransData = NULL;
277 REAL8 f0 = 1.0;
278 REAL8 phiFac = 1.0, fFac = 1.0;
279
280 /* Heterodyning phase factor LAL_TWOPI*output->f0*output->deltaT,
281 and phase offset at the start of the series
282 LAL_TWOPI*output->f0*(time offset). */
283 REAL8 heteroFac, phi0;
284
285 /* Variables required by the TCENTRE() macro, above. */
286 REAL8 realIndex;
287 INT4 intIndex;
288 REAL8 indexFrac;
289
290 INITSTATUS( stat );
292
293 /* Make sure parameter structures and their fields exist. */
295 SIMULATECOHERENTGWH_MSGENUL );
296 if ( !( CWsignal->a ) ) {
298 SIMULATECOHERENTGWH_MSGESIG );
299 }
300 ASSERT( CWsignal->a->data, stat,
301 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
302 ASSERT( CWsignal->a->data->data, stat,
303 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
304 if ( !( CWsignal->phi ) ) {
306 SIMULATECOHERENTGWH_MSGESIG );
307 }
308 ASSERT( CWsignal->phi->data, stat,
309 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
310 ASSERT( CWsignal->phi->data->data, stat,
311 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
312 if ( CWsignal->f ) {
313 ASSERT( CWsignal->f->data, stat,
314 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
315 ASSERT( CWsignal->f->data->data, stat,
316 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
317 }
318 if ( CWsignal->shift ) {
319 ASSERT( CWsignal->shift->data, stat,
320 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
321 ASSERT( CWsignal->shift->data->data, stat,
322 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
323 }
325 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
326 if ( ( transfer = ( detector->transfer != NULL ) ) ) {
327 ASSERT( detector->transfer->data, stat,
328 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
329 ASSERT( detector->transfer->data->data, stat,
330 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
331 }
333 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
334 ASSERT( output->data, stat,
335 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
336 ASSERT( output->data->data, stat,
337 SIMULATECOHERENTGWH_ENUL, SIMULATECOHERENTGWH_MSGENUL );
338
339 /* Check dimensions of amplitude array. */
340 ASSERT( CWsignal->a->data->vectorLength == 2, stat,
341 SIMULATECOHERENTGWH_EDIM, SIMULATECOHERENTGWH_MSGEDIM );
342
343 /* Make sure we never divide by zero. */
344 ASSERT( CWsignal->a->deltaT != 0.0, stat,
345 SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
346 ASSERT( CWsignal->phi->deltaT != 0.0, stat,
347 SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
348 aDt = output->deltaT / CWsignal->a->deltaT;
349 phiDt = output->deltaT / CWsignal->phi->deltaT;
350 ASSERT( aDt != 0.0, stat,
351 SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
352 ASSERT( phiDt != 0.0, stat,
353 SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
354 if ( CWsignal->f ) {
355 ASSERT( CWsignal->f->deltaT != 0.0, stat,
356 SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
357 fDt = output->deltaT / CWsignal->f->deltaT;
358 ASSERT( fDt != 0.0, stat,
359 SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
360 } else {
361 fDt = 0.0;
362 }
363 if ( CWsignal->shift ) {
364 ASSERT( CWsignal->shift->deltaT != 0.0, stat,
365 SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
366 shiftDt = output->deltaT / CWsignal->shift->deltaT;
367 ASSERT( shiftDt != 0.0, stat,
368 SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
369 } else {
370 shiftDt = 0.0;
371 }
372 if ( transfer ) {
373 ASSERT( detector->transfer->deltaF != 0.0, stat,
374 SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
375 fFac = 1.0 / detector->transfer->deltaF;
376 phiFac = fFac / ( LAL_TWOPI * CWsignal->phi->deltaT );
377 f0 = detector->transfer->f0 / detector->transfer->deltaF;
378 }
379 heteroFac = LAL_TWOPI * output->f0 * output->deltaT;
380 phi0 = ( REAL8 )( output->epoch.gpsSeconds -
381 detector->heterodyneEpoch.gpsSeconds );
382 phi0 += 0.000000001 * ( REAL8 )( output->epoch.gpsNanoSeconds -
383 detector->heterodyneEpoch.gpsNanoSeconds );
384 phi0 *= LAL_TWOPI * output->f0;
385 if ( phi0 > 1.0 / LAL_REAL8_EPS ) {
386 LALWarning( stat, "REAL8 arithmetic is not sufficient to maintain"
387 " heterodyne phase to within a radian." );
388 }
389
390 /* Check units on input, and set units on output. */
391 {
392 if ( CWsignal->f ) {
393 ASSERT( XLALUnitCompare( &( CWsignal->f->sampleUnits ), &lalHertzUnit ) == 0, stat, SIMULATECOHERENTGWH_EUNIT, SIMULATECOHERENTGWH_MSGEUNIT );
394 }
395 ASSERT( XLALUnitCompare( &( CWsignal->phi->sampleUnits ), &lalDimensionlessUnit ) == 0, stat, SIMULATECOHERENTGWH_EUNIT, SIMULATECOHERENTGWH_MSGEUNIT );
396 if ( CWsignal->shift ) {
397 ASSERT( XLALUnitCompare( &( CWsignal->shift->sampleUnits ), &lalDimensionlessUnit ) == 0, stat, SIMULATECOHERENTGWH_EUNIT, SIMULATECOHERENTGWH_MSGEUNIT );
398 }
399 if ( transfer ) {
400 if ( XLALUnitMultiply( &( output->sampleUnits ), &( CWsignal->a->sampleUnits ), &( detector->transfer->sampleUnits ) ) == NULL ) {
401 ABORT( stat, SIMULATECOHERENTGWH_EUNIT, SIMULATECOHERENTGWH_MSGEUNIT );
402 }
403 } else {
404 output->sampleUnits = CWsignal->a->sampleUnits;
405 }
406 strncpy( output->name, CWsignal->a->name, LALNameLength );
407 }
408
409 /* Define temporary variables to access the data of CWsignal->a,
410 CWsignal->f, and CWsignal->phi. */
411 aData = CWsignal->a->data->data;
412 INT4 aLen = CWsignal->a->data->length * CWsignal->a->data->vectorLength;
413 phiData = CWsignal->phi->data->data;
414 INT4 phiLen = CWsignal->phi->data->length;
415 outData = output->data->data;
416 INT4 fLen = 0, shiftLen = 0;
417 if ( CWsignal->f ) {
418 fData = CWsignal->f->data->data;
419 fLen = CWsignal->f->data->length;
420 } else {
421 fData = NULL;
422 }
423
424 if ( CWsignal->shift ) {
425 shiftData = CWsignal->shift->data->data;
426 shiftLen = CWsignal->shift->data->length;
427 } else {
428 shiftData = NULL;
429 }
430
431 /* Convert source position to equatorial coordinates, if
432 required. */
433 if ( detector->site ) {
434 source = CWsignal->position;
435 if ( source.system != COORDINATESYSTEM_EQUATORIAL ) {
436 ConvertSkyParams params; /* parameters for conversion */
437 EarthPosition location; /* location of detector */
438 params.gpsTime = &( output->epoch );
440 if ( source.system == COORDINATESYSTEM_HORIZON ) {
441 params.zenith = &( location.geodetic );
442 location.x = detector->site->location[0];
443 location.y = detector->site->location[1];
444 location.z = detector->site->location[2];
445 TRY( LALGeocentricToGeodetic( stat->statusPtr, &location ),
446 stat );
447 }
448 TRY( LALConvertSkyCoordinates( stat->statusPtr, &source,
449 &source, &params ), stat );
450 }
451 }
452
453 /* Generate the table of propagation delays.
454 dtDelayBy2 = (UINT4)( 38924.9/sqrt( output->f0 +
455 1.0/output->deltaT ) ); */
456 delayDt = output->deltaT / ( 2.0 * dtDelayBy2 );
457 nMax = ( UINT4 )( output->data->length * delayDt ) + 3;
458 TRY( LALDCreateVector( stat->statusPtr, &delay, nMax ), stat );
459 delayData = delay->data;
460
461 /* Compute delay from solar system barycentre. */
462 if ( detector->site && detector->ephemerides ) {
463 LIGOTimeGPS gpsTime; /* detector time when we compute delay */
464 EarthState state; /* Earth position info at that time */
465 BarycenterInput input; /* input structure to XLALBarycenter() */
466 EmissionTime emit; /* output structure from XLALBarycenter() */
467
468 /* Arrange nested pointers, and set initial values. */
469 gpsTime = input.tgps = output->epoch;
470 gpsTime.gpsSeconds -= dtDelayBy2;
471 input.tgps.gpsSeconds -= dtDelayBy2;
472 input.site = *( detector->site );
473 for ( i = 0; i < 3; i++ ) {
474 input.site.location[i] /= LAL_C_SI;
475 }
476 input.alpha = source.longitude;
477 input.delta = source.latitude;
478 input.dInv = 0.0;
479 delayMin = delayMax = 1.1 * LAL_AU_SI / ( LAL_C_SI * output->deltaT );
480 delayMax *= -1;
481
482 /* Compute table. */
483 for ( i = 0; i < nMax; i++ ) {
484 REAL8 tDelay; /* propagation time */
485 if ( XLALBarycenterEarth( &state, &gpsTime,
486 detector->ephemerides ) != XLAL_SUCCESS ) {
487 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
488 ABORTXLAL( stat );
489 }
490 if ( XLALBarycenter( &emit, &input, &state ) != XLAL_SUCCESS ) {
491 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
492 ABORTXLAL( stat );
493 }
494 delayData[i] = tDelay = emit.deltaT / output->deltaT;
495 if ( tDelay < delayMin ) {
496 delayMin = tDelay;
497 }
498 if ( tDelay > delayMax ) {
499 delayMax = tDelay;
500 }
501 gpsTime.gpsSeconds += 2 * dtDelayBy2;
502 input.tgps.gpsSeconds += 2 * dtDelayBy2;
503 }
504 }
505
506 /* No information from which to compute delays. */
507 else {
508 LALInfo( stat, "Detector site and ephemerides absent; simulating hplus with no"
509 " propagation delays" );
510 memset( delayData, 0, nMax * sizeof( REAL8 ) );
511 delayMin = delayMax = 0.0;
512 }
513
514 /* Generate the table of polarization response functions. */
515 polDt = output->deltaT / ( 2.0 * dtPolBy2 );
516 nMax = ( UINT4 )( output->data->length * polDt ) + 3;
517 memset( &polResponse, 0, sizeof( LALDetAMResponseSeries ) );
518 polResponse.pPlus = ( REAL4TimeSeries * )
519 LALMalloc( sizeof( REAL4TimeSeries ) );
520 polResponse.pCross = ( REAL4TimeSeries * )
521 LALMalloc( sizeof( REAL4TimeSeries ) );
522 polResponse.pScalar = ( REAL4TimeSeries * )
523 LALMalloc( sizeof( REAL4TimeSeries ) );
524 if ( !polResponse.pPlus || !polResponse.pCross ||
525 !polResponse.pScalar ) {
526 if ( polResponse.pPlus ) {
527 LALFree( polResponse.pPlus );
528 }
529 if ( polResponse.pCross ) {
530 LALFree( polResponse.pCross );
531 }
532 if ( polResponse.pScalar ) {
533 LALFree( polResponse.pScalar );
534 }
535 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
537 SIMULATECOHERENTGWH_MSGEMEM );
538 }
539 memset( polResponse.pPlus, 0, sizeof( REAL4TimeSeries ) );
540 memset( polResponse.pCross, 0, sizeof( REAL4TimeSeries ) );
541 memset( polResponse.pScalar, 0, sizeof( REAL4TimeSeries ) );
542 LALSCreateVector( stat->statusPtr, &( polResponse.pPlus->data ),
543 nMax );
544 BEGINFAIL( stat ) {
545 LALFree( polResponse.pPlus );
546 LALFree( polResponse.pCross );
547 LALFree( polResponse.pScalar );
548 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
549 }
550 ENDFAIL( stat );
551 LALSCreateVector( stat->statusPtr, &( polResponse.pCross->data ),
552 nMax );
553 BEGINFAIL( stat ) {
554 TRY( LALSDestroyVector( stat->statusPtr,
555 &( polResponse.pPlus->data ) ), stat );
556 LALFree( polResponse.pPlus );
557 LALFree( polResponse.pCross );
558 LALFree( polResponse.pScalar );
559 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
560 }
561 ENDFAIL( stat );
562 LALSCreateVector( stat->statusPtr, &( polResponse.pScalar->data ),
563 nMax );
564 BEGINFAIL( stat ) {
565 TRY( LALSDestroyVector( stat->statusPtr,
566 &( polResponse.pPlus->data ) ), stat );
567 TRY( LALSDestroyVector( stat->statusPtr,
568 &( polResponse.pCross->data ) ), stat );
569 LALFree( polResponse.pPlus );
570 LALFree( polResponse.pCross );
571 LALFree( polResponse.pScalar );
572 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
573 }
574 ENDFAIL( stat );
575 plusData = polResponse.pPlus->data->data;
576 crossData = polResponse.pCross->data->data;
577 INT4 plusLen = polResponse.pPlus->data->length;
578 INT4 crossLen = polResponse.pCross->data->length;
579 if ( plusLen != crossLen ) {
580 XLALPrintError( "plusLen = %d != crossLen = %d\n", plusLen, crossLen );
581 ABORT( stat, SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
582 }
583
584 if ( detector->site ) {
585 LALSource polSource; /* position and polarization angle */
586 LALDetAndSource input; /* response input structure */
587 LALTimeIntervalAndNSample params; /* response parameter structure */
588
589 /* Arrange nested pointers, and set initial values. */
590 polSource.equatorialCoords = source;
591 polSource.orientation = ( REAL8 )( CWsignal->psi );
592 input.pSource = &polSource;
593 input.pDetector = detector->site;
594 params.epoch = output->epoch;
595 params.epoch.gpsSeconds -= dtPolBy2;
596 params.deltaT = 2.0 * dtPolBy2;
597 params.nSample = nMax;
598
599 /* Compute table of responses. */
600 LALComputeDetAMResponseSeries( stat->statusPtr, &polResponse,
601 &input, &params );
602 BEGINFAIL( stat ) {
603 TRY( LALSDestroyVector( stat->statusPtr,
604 &( polResponse.pPlus->data ) ), stat );
605 TRY( LALSDestroyVector( stat->statusPtr,
606 &( polResponse.pCross->data ) ), stat );
607 TRY( LALSDestroyVector( stat->statusPtr,
608 &( polResponse.pScalar->data ) ), stat );
609 LALFree( polResponse.pPlus );
610 LALFree( polResponse.pCross );
611 LALFree( polResponse.pScalar );
612 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
613 }
614 ENDFAIL( stat );
615 } else {
616 /* No detector site, so just simulate response to hplus. */
617 for ( i = 0; i < nMax; i++ ) {
618 plusData[i] = 1.0;
619 crossData[i] = 0.0;
620 }
621 }
622 /* Free memory for the unused scalar mode. */
623 TRY( LALSDestroyVector( stat->statusPtr,
624 &( polResponse.pScalar->data ) ), stat );
625 LALFree( polResponse.pScalar );
626
627 /* Decompose the transfer function into an amplitude and phase
628 response. */
629 INT4 phiTransLen = 0, aTransLen = 0;
630 if ( transfer ) {
631 nMax = detector->transfer->data->length;
632 LALSCreateVector( stat->statusPtr, &phiTemp, nMax );
633 BEGINFAIL( stat ) {
634 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
635 TRY( LALSDestroyVector( stat->statusPtr,
636 &( polResponse.pPlus->data ) ), stat );
637 TRY( LALSDestroyVector( stat->statusPtr,
638 &( polResponse.pCross->data ) ), stat );
639 LALFree( polResponse.pPlus );
640 LALFree( polResponse.pCross );
641 }
642 ENDFAIL( stat );
643 LALCVectorAngle( stat->statusPtr, phiTemp,
644 detector->transfer->data );
645 BEGINFAIL( stat ) {
646 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
647 TRY( LALSDestroyVector( stat->statusPtr, &phiTemp ), stat );
648 TRY( LALSDestroyVector( stat->statusPtr,
649 &( polResponse.pPlus->data ) ), stat );
650 TRY( LALSDestroyVector( stat->statusPtr,
651 &( polResponse.pCross->data ) ), stat );
652 LALFree( polResponse.pPlus );
653 LALFree( polResponse.pCross );
654 }
655 ENDFAIL( stat );
656 LALSCreateVector( stat->statusPtr, &phiTransfer, nMax );
657 BEGINFAIL( stat ) {
658 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
659 TRY( LALSDestroyVector( stat->statusPtr, &phiTemp ), stat );
660 TRY( LALSDestroyVector( stat->statusPtr,
661 &( polResponse.pPlus->data ) ), stat );
662 TRY( LALSDestroyVector( stat->statusPtr,
663 &( polResponse.pCross->data ) ), stat );
664 LALFree( polResponse.pPlus );
665 LALFree( polResponse.pCross );
666 }
667 ENDFAIL( stat );
668 LALUnwrapREAL4Angle( stat->statusPtr, phiTransfer, phiTemp );
669 BEGINFAIL( stat ) {
670 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
671 TRY( LALSDestroyVector( stat->statusPtr, &phiTemp ), stat );
672 TRY( LALSDestroyVector( stat->statusPtr, &phiTransfer ), stat );
673 TRY( LALSDestroyVector( stat->statusPtr,
674 &( polResponse.pPlus->data ) ), stat );
675 TRY( LALSDestroyVector( stat->statusPtr,
676 &( polResponse.pCross->data ) ), stat );
677 LALFree( polResponse.pPlus );
678 LALFree( polResponse.pCross );
679 }
680 ENDFAIL( stat );
681 TRY( LALSDestroyVector( stat->statusPtr, &phiTemp ), stat );
682 LALSCreateVector( stat->statusPtr, &aTransfer, nMax );
683 BEGINFAIL( stat ) {
684 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
685 TRY( LALSDestroyVector( stat->statusPtr, &phiTransfer ), stat );
686 TRY( LALSDestroyVector( stat->statusPtr,
687 &( polResponse.pPlus->data ) ), stat );
688 TRY( LALSDestroyVector( stat->statusPtr,
689 &( polResponse.pCross->data ) ), stat );
690 LALFree( polResponse.pPlus );
691 LALFree( polResponse.pCross );
692 }
693 ENDFAIL( stat );
694 LALCVectorAbs( stat->statusPtr, aTransfer,
695 detector->transfer->data );
696 BEGINFAIL( stat ) {
697 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
698 TRY( LALSDestroyVector( stat->statusPtr, &phiTransfer ), stat );
699 TRY( LALSDestroyVector( stat->statusPtr, &aTransfer ), stat );
700 TRY( LALSDestroyVector( stat->statusPtr,
701 &( polResponse.pPlus->data ) ), stat );
702 TRY( LALSDestroyVector( stat->statusPtr,
703 &( polResponse.pCross->data ) ), stat );
704 LALFree( polResponse.pPlus );
705 LALFree( polResponse.pCross );
706 }
707 ENDFAIL( stat );
708 phiTransData = phiTransfer->data;
709 phiTransLen = phiTransfer->length;
710 aTransData = aTransfer->data;
711 aTransLen = aTransfer->length;
712 }
713 if ( aTransLen != phiTransLen ) {
714 XLALPrintError( "aTransLen = %d != phiTransLen = %d\n", aTransLen, phiTransLen );
715 ABORT( stat, SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
716 }
717
718 /* Compute offsets for interpolating the signal, delay, and
719 response functions. */
720 aOff = ( output->epoch.gpsSeconds -
721 CWsignal->a->epoch.gpsSeconds ) /
722 CWsignal->a->deltaT;
723 aOff += ( output->epoch.gpsNanoSeconds -
724 CWsignal->a->epoch.gpsNanoSeconds ) * 1.0e-9 /
725 CWsignal->a->deltaT;
726 phiOff = ( output->epoch.gpsSeconds -
727 CWsignal->phi->epoch.gpsSeconds ) /
728 CWsignal->phi->deltaT;
729 phiOff += ( output->epoch.gpsNanoSeconds -
730 CWsignal->phi->epoch.gpsNanoSeconds ) * 1.0e-9 /
731 CWsignal->phi->deltaT;
732 if ( CWsignal->f ) {
733 fOff = ( output->epoch.gpsSeconds -
734 CWsignal->f->epoch.gpsSeconds ) /
735 CWsignal->f->deltaT;
736 fOff += ( output->epoch.gpsNanoSeconds -
737 CWsignal->f->epoch.gpsNanoSeconds ) * 1.0e-9 /
738 CWsignal->f->deltaT;
739 } else {
740 fOff = 0.0;
741 }
742 if ( CWsignal->shift ) {
743 shiftOff = ( output->epoch.gpsSeconds -
744 CWsignal->shift->epoch.gpsSeconds ) /
745 CWsignal->shift->deltaT;
746 shiftOff += ( output->epoch.gpsNanoSeconds -
747 CWsignal->shift->epoch.gpsNanoSeconds ) * 1.0e-9 /
748 CWsignal->shift->deltaT;
749 } else {
750 shiftOff = 0.0;
751 }
752 polOff = 0.5;
753 delayOff = 0.5;
754
755 /* Compute initial value of i, ensuring that we will never index
756 CWsignal->a or CWsignal->phi below their range. */
757 i = 0;
758 if ( aOff + ( i + delayMin ) * aDt < 0.0 ) {
759 INT4 j = ( INT4 )floor( -aOff / aDt - delayMax );
760 if ( i < j ) {
761 i = j;
762 }
763 while ( ( i < ( INT4 )( output->data->length ) ) &&
764 ( aOff + TCENTRE( i ) * aDt < 0.0 ) ) {
765 i++;
766 }
767 }
768 if ( phiOff + ( i + delayMin ) * phiDt < 0.0 ) {
769 INT4 j = ( INT4 )( -phiOff / phiDt - delayMax );
770 if ( i < j ) {
771 i = j;
772 }
773 while ( ( i < ( INT4 )( output->data->length ) ) &&
774 ( phiOff + TCENTRE( i ) * phiDt < 0.0 ) ) {
775 i++;
776 }
777 }
778 if ( i >= ( INT4 )( output->data->length ) ) {
779 LALWarning( stat, "Signal starts after the end of the output"
780 " time series." );
781 i = ( INT4 )( output->data->length );
782 }
783
784 /* Compute final value of i, ensuring that we will never index
785 CWsignal->a or CWsignal->phi above their range. */
786 n = output->data->length - 1;
787 INT4 nMax_a = CWsignal->a->data->length - 1;
788 if ( aOff + ( n + delayMax ) * aDt > nMax_a ) {
789 INT4 j = ( INT4 )( ( nMax_a - aOff ) / aDt - delayMin + 1.0 );
790 if ( n > j ) {
791 n = j;
792 }
793 while ( ( n >= 0 ) &&
794 ( ( INT4 )floor( aOff + TCENTRE( n ) * aDt ) > nMax ) ) {
795 n--;
796 }
797 }
798 nMax = CWsignal->phi->data->length - 1;
799 if ( phiOff + ( n + delayMax ) * phiDt > nMax ) {
800 INT4 j = ( INT4 )( ( nMax - phiOff ) / phiDt - delayMin + 1.0 );
801 if ( n > j ) {
802 n = j;
803 }
804 while ( ( n >= 0 ) &&
805 ( ( INT4 )floor( phiOff + TCENTRE( n ) * phiDt ) > nMax ) ) {
806 n--;
807 }
808 }
809 if ( n < 0 ) {
810 LALWarning( stat, "CWsignal ends before the start of the output"
811 " time series." );
812 n = -1;
813 }
814
815 /* Compute the values of i for which CWsignal->f is given. */
816 if ( CWsignal->f ) {
817 fInit = i;
818 if ( fOff + ( fInit + delayMin ) * fDt < 0.0 ) {
819 INT4 j = ( INT4 )floor( -fOff / fDt - delayMax );
820 if ( fInit < j ) {
821 fInit = j;
822 }
823 while ( ( fInit <= n ) &&
824 ( fOff + TCENTRE( fInit ) * fDt < 0.0 ) ) {
825 fInit++;
826 }
827 }
828 fFinal = n;
829 nMax = CWsignal->f->data->length - 1;
830 if ( fOff + ( fFinal + delayMax ) * fDt > nMax ) {
831 INT4 j = ( INT4 )( ( nMax - fOff ) / fDt - delayMin + 1.0 );
832 if ( fFinal > j ) {
833 fFinal = j;
834 }
835 while ( ( fFinal >= i ) &&
836 ( ( INT4 )floor( fOff + TCENTRE( fFinal ) * fDt ) > nMax ) ) {
837 fFinal--;
838 }
839 }
840 } else {
841 fInit = n + 1;
842 fFinal = i - 1;
843 }
844
845 /* Compute the values of i for which CWsignal->shift is given. */
846 if ( CWsignal->shift ) {
847 shiftInit = i;
848 if ( shiftOff + ( shiftInit + delayMin ) * shiftDt < 0.0 ) {
849 INT4 j = ( INT4 )floor( -shiftOff / shiftDt - delayMax );
850 if ( shiftInit < j ) {
851 shiftInit = j;
852 }
853 while ( ( shiftInit <= n ) &&
854 ( shiftOff + TCENTRE( shiftInit ) * shiftDt < 0.0 ) ) {
855 shiftInit++;
856 }
857 }
858 shiftFinal = n;
859 nMax = CWsignal->shift->data->length - 1;
860 if ( shiftOff + ( shiftFinal + delayMax ) * shiftDt > nMax ) {
861 INT4 j = ( INT4 )( ( nMax - shiftOff ) / shiftDt - delayMin + 1.0 );
862 if ( shiftFinal > j ) {
863 shiftFinal = j;
864 }
865 while ( ( shiftFinal >= i ) &&
866 ( ( INT4 )floor( shiftOff + TCENTRE( shiftFinal ) * shiftDt ) > nMax ) ) {
867 shiftFinal--;
868 }
869 }
870 } else {
871 shiftInit = n + 1;
872 shiftFinal = i - 1;
873 }
874
875 /* Set output to zero where the CWsignal is not defined. */
876 if ( i > 0 ) {
877 memset( output->data->data, 0, i * sizeof( REAL4 ) );
878 }
879 if ( ( nMax = output->data->length - n - 1 ) > 0 ) {
880 memset( output->data->data + n + 1, 0, nMax * sizeof( REAL4 ) );
881 }
882
883 /* Keep track of the frequency range of the transfer function, so
884 that we don't try to interpolate it out of its range. */
885 if ( transfer ) {
886 nMax = detector->transfer->data->length - 1;
887 }
888
889 /* Start computing responses. */
890 for ( ; i <= n; i++ ) {
891 REAL8 iCentre = TCENTRE( i ); /* value of i + propagation delays */
892 REAL8 x; /* interpolation point in arrays */
893 INT4 j; /* array index preceding x */
894 REAL8 frac; /* value of x - j */
895 REAL4 a1, a2; /* current signal amplitudes */
896 REAL8 phi = 0.0; /* current signal phase */
897 REAL4 f = 0.0; /* current signal frequency */
898 REAL4 shift = 0.0; /* current signal polarization shift */
899 REAL4 aTrans, phiTrans; /* current values of the transfer function */
900 REAL4 oPlus, oCross; /* current output amplitudes */
901 REAL4 sp, cp, ss, cs; /* sine and cosine of shift and phase */
902
903 /* Interpolate the signal amplitude. */
904 x = aOff + iCentre * aDt;
905 j = ( INT4 )floor( x );
906 frac = ( REAL8 )( x - j );
907 j *= 2;
908 if ( j + 3 >= aLen ) {
909 XLALPrintError( "Interpolation error: no point at or after last sample for {a1,a2}: i = %d, n = %d, j = %d, aLen = %d", i, n, j, aLen );
910 ABORT( stat, SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
911 }
912 {
913 a1 = frac * aData[j + 2] + ( 1.0 - frac ) * aData[j];
914 a2 = frac * aData[j + 3] + ( 1.0 - frac ) * aData[j + 1];
915 }
916
917 /* Interpolate the polarization shift. */
918 if ( ( i < shiftInit ) || ( i > shiftFinal ) ) {
919 shift = 0.0;
920 } else {
921 x = shiftOff + iCentre * shiftDt;
922 j = ( INT4 )floor( x );
923 frac = ( REAL8 )( x - j );
924
925 if ( j + 1 >= shiftLen ) {
926 XLALPrintError( "Interpolation error: no point at or after last sample for 'shift'" );
927 ABORT( stat, SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
928 }
929 shift = frac * shiftData[j + 1] + ( 1.0 - frac ) * shiftData[j];
930 }
931
932 /* Interpolate the signal phase, and apply any heterodyning. */
933 x = phiOff + iCentre * phiDt;
934 j = ( INT4 )floor( x );
935 frac = ( REAL8 )( x - j );
936
937 if ( j + 1 >= phiLen ) {
938 XLALPrintError( "Interpolation error: no point at or after last sample for 'phi'" );
939 ABORT( stat, SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
940 }
941 phi = frac * phiData[j + 1] + ( 1.0 - frac ) * phiData[j];
942 phi -= heteroFac * i + phi0;
943
944 /* Compute the frequency and apply the transfer function. */
945 if ( transfer ) {
946 if ( ( i < fInit ) || ( i > fFinal ) ) {
947 f = ( phiData[j + 1] - phiData[j] ) * phiFac;
948 pFlag = 1;
949 } else {
950 x = fOff + iCentre * fDt;
951 j = ( INT4 )floor( x );
952 frac = ( REAL8 )( x - j );
953 if ( j + 1 >= fLen ) {
954 XLALPrintError( "Interpolation error: no point at or after last sample for 'f'" );
955 ABORT( stat, SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
956 }
957 f = frac * fData[j + 1] + ( 1.0 - frac ) * fData[j];
958 f *= fFac;
959 }
960 x = f - f0;
961 if ( ( x < 0.0 ) || ( x > nMax ) ) {
962 aTrans = 0.0;
963 phiTrans = 0.0;
964 fFlag = 1;
965 } else {
966 j = ( INT4 )floor( x );
967 frac = ( REAL8 )( x - j );
968 if ( j + 1 >= aTransLen ) {
969 XLALPrintError( "Interpolation error: no point at or after last sample for '{aTrans,phiTrans}'" );
970 ABORT( stat, SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
971 }
972 {
973 aTrans = frac * aTransData[j + 1] + ( 1.0 - frac ) * aTransData[j];
974 phiTrans = frac * phiTransData[j + 1] + ( 1.0 - frac ) * phiTransData[j];
975 }
976 }
977 a1 *= aTrans;
978 a2 *= aTrans;
979 phi += phiTrans;
980 }
981
982 /* Compute components of output. */
983 if ( XLALSinCosLUT( &ss, &cs, shift ) != XLAL_SUCCESS ) {
984 ABORT( stat, LAL_EXLAL, "XLALSinCosLUT(&ss, &cs, shift) failed" );
985 }
986 if ( XLALSinCosLUT( &sp, &cp, phi ) != XLAL_SUCCESS ) {
987 ABORT( stat, LAL_EXLAL, "XLALSinCosLUT(&sp, &cp, phi) failed" );
988 }
989 oPlus = a1 * cs * cp - a2 * ss * sp;
990 oCross = a1 * ss * cp + a2 * cs * sp;
991 /* oPlus = a1*cos( shift )*cos( phi ) - a2*sin( shift )*sin( phi ); */
992 /* oCross = a1*sin( shift )*cos( phi ) + a2*cos( shift )*sin( phi ); */
993
994 /* Interpolate the polarization response, and compute output. */
995 x = polOff + i * polDt;
996 j = ( INT4 )floor( x );
997 frac = ( REAL8 )( x - j );
998 if ( j + 1 >= plusLen ) {
999 XLALPrintError( "Interpolation error: no point at or after last sample for '{oPlus,oCross}'" );
1000 ABORT( stat, SIMULATECOHERENTGWH_EBAD, SIMULATECOHERENTGWH_MSGEBAD );
1001 }
1002 {
1003 oPlus *= frac * plusData[j + 1] + ( 1.0 - frac ) * plusData[j];
1004 oCross *= frac * crossData[j + 1] + ( 1.0 - frac ) * crossData[j];
1005 }
1006
1007 outData[i] = oPlus + oCross;
1008 }
1009
1010 /* Warn if we ever stepped outside of the frequency domain of the
1011 transfer function, or if we had to estimate f from phi. */
1012 if ( fFlag )
1013 LALWarning( stat, "Signal passed outside of the frequency domain"
1014 " of the transfer function (transfer function is"
1015 " treated as zero outside its specified domain)" );
1016 if ( pFlag )
1017 LALInfo( stat, "Signal frequency was estimated by differencing"
1018 " the signal phase" );
1019
1020 /* Cleanup and exit. */
1021 TRY( LALDDestroyVector( stat->statusPtr, &delay ), stat );
1022 if ( transfer ) {
1023 TRY( LALSDestroyVector( stat->statusPtr, &phiTransfer ), stat );
1024 TRY( LALSDestroyVector( stat->statusPtr, &aTransfer ), stat );
1025 }
1026 TRY( LALSDestroyVector( stat->statusPtr,
1027 &( polResponse.pPlus->data ) ), stat );
1028 TRY( LALSDestroyVector( stat->statusPtr,
1029 &( polResponse.pCross->data ) ), stat );
1030 LALFree( polResponse.pPlus );
1031 LALFree( polResponse.pCross );
1033 RETURN( stat );
1034
1035} /* LALPulsarSimulateCoherentGW() */
int j
#define LALMalloc(n)
#define LALFree(p)
#define ABORT(statusptr, code, mesg)
#define ENDFAIL(statusptr)
#define LAL_EXLAL
#define TRY(func, statusptr)
#define ATTATCHSTATUSPTR(statusptr)
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
#define ABORTXLAL(sp)
#define BEGINFAIL(statusptr)
#define SIMULATECOHERENTGWH_EUNIT
Bad input units.
#define SIMULATECOHERENTGWH_ENUL
Unexpected null pointer in arguments.
#define SIMULATECOHERENTGWH_ESIG
Input signal must specify amplitude and phase functions.
#define SIMULATECOHERENTGWH_EMEM
Memory allocation error.
#define TCENTRE(time)
#define SIMULATECOHERENTGWH_EDIM
Amplitude must be a 2-dimensional vector.
#define SIMULATECOHERENTGWH_EBAD
A sampling interval is (effectively) zero.
const double a2
void LALComputeDetAMResponseSeries(LALStatus *status, LALDetAMResponseSeries *pResponseSeries, const LALDetAndSource *pDetAndSource, const LALTimeIntervalAndNSample *pTimeInfo)
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 LAL_REAL8_EPS
#define LAL_TWOPI
unsigned char BOOLEAN
double REAL8
#define XLAL_INIT_DECL(var,...)
uint32_t UINT4
int32_t INT4
float REAL4
LALNameLength
int LALWarning(LALStatus *status, const char *warning)
int LALInfo(LALStatus *status, const char *info)
int XLALPulsarSimulateCoherentGW(REAL4TimeSeries *output, PulsarCoherentGW *CWsignal, PulsarDetectorResponse *detector)
FIXME: Temporary XLAL-wapper to LAL-function LALPulsarSimulateCoherentGW()
void LALPulsarSimulateCoherentGW(LALStatus *stat, REAL4TimeSeries *output, PulsarCoherentGW *CWsignal, PulsarDetectorResponse *detector)
Computes the response of a detector to a coherent gravitational wave.
int XLALSinCosLUT(REAL4 *sinx, REAL4 *cosx, REAL8 x)
Calculate sin(x) and cos(x) to roughly 1e-7 precision using a lookup-table and Taylor-expansion.
Definition: SinCosLUT.c:83
void LALConvertSkyCoordinates(LALStatus *stat, SkyPosition *output, SkyPosition *input, ConvertSkyParams *params)
COORDINATESYSTEM_HORIZON
COORDINATESYSTEM_EQUATORIAL
void LALGeocentricToGeodetic(LALStatus *stat, EarthPosition *location)
int XLALUnitCompare(const LALUnit *unit1, const LALUnit *unit2)
const LALUnit lalHertzUnit
const LALUnit lalDimensionlessUnit
LALUnit * XLALUnitMultiply(LALUnit *output, const LALUnit *unit1, const LALUnit *unit2)
void LALDCreateVector(LALStatus *, REAL8Vector **, UINT4)
void LALDDestroyVector(LALStatus *, REAL8Vector **)
void LALSDestroyVector(LALStatus *, REAL4Vector **)
void LALSCreateVector(LALStatus *, REAL4Vector **, UINT4)
void LALCVectorAngle(LALStatus *status, REAL4Vector *out, const COMPLEX8Vector *in)
void LALCVectorAbs(LALStatus *status, REAL4Vector *out, const COMPLEX8Vector *in)
void LALUnwrapREAL4Angle(LALStatus *status, REAL4Vector *out, const REAL4Vector *in)
#define XLAL_CHECK(assertion,...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_SUCCESS
XLAL_EINVAL
XLAL_EFAILED
ss
n
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.
SkyPosition geodetic
Basic output structure of LALBarycenterEarth.c.
Basic output structure produced by LALBarycenter.c.
REAL8 deltaT
(TDB) - (GPS)
REAL4TimeSeries * pCross
REAL4TimeSeries * pPlus
REAL4TimeSeries * pScalar
LALSource * pSource
const LALDetector * pDetector
REAL8 location[3]
SkyPosition equatorialCoords
REAL8 orientation
INT4 gpsNanoSeconds
This structure stores a representation of a plane gravitational wave propagating from a particular po...
REAL4TimeSeries * f
A time-sampled sequence storing the instantaneous frequency , in Hz.
REAL4 psi
The polarization angle , in radians, as defined in Appendix B of .
SkyPosition position
The location of the source in the sky; this should be in equatorial celestial coordinates,...
REAL4TimeVectorSeries * a
A time-sampled two-dimensional vector storing the amplitudes and , in dimensionless strain.
REAL4TimeSeries * shift
A time-sampled sequence storing the polarization shift , in radians.
UINT4 dtPolBy2
A user defined half-interval time step for the polarisation response look-up table (will default to 3...
UINT4 dtDelayBy2
A user specified half-interval time step for the Doppler delay look-up table (will default to 400s if...
REAL8TimeSeries * phi
A time-sampled sequence storing the phase function , in radians.
This structure contains information required to determine the response of a detector to a gravitation...
REAL4Sequence * data
LALUnit sampleUnits
LIGOTimeGPS epoch
CHAR name[LALNameLength]
REAL4VectorSequence * data
REAL4 * data
REAL8Sequence * data
LALUnit sampleUnits
LIGOTimeGPS epoch
REAL8 * data
REAL8 longitude
REAL8 latitude
CoordinateSystem system
LIGOTimeGPS epoch