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
PtoleMetric.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 David M. Whitbeck, Thomas Essinger-Hileman, Jolien Creighton, Ian Jones, Benjamin Owen, Reinhard Prix, Karl Wette
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 <stdlib.h>
22#include <gsl/gsl_matrix.h>
23#include <lal/AVFactories.h>
24#include <lal/DetectorSite.h>
25#include <lal/LALStdlib.h>
26#include <lal/PtoleMetric.h>
27#include <lal/GetEarthTimes.h>
28#include <lal/Factorial.h>
29
30/* Bounds on acceptable parameters, may be somewhat arbitrary */
31#define MIN_DURATION (LAL_DAYSID_SI/LAL_TWOPI) /* Metric acts funny if duration too short */
32#define MIN_MAXFREQ 1. /* Arbitrary */
33
34/* A private factorial function */
35/* static int factrl( int ); */
36
37/**
38 * \author Jones D. I., Owen, B. J., and Whitbeck, D. M.
39 * \date 2001-2005
40 * \brief Computes metric components for a pulsar search in the ``Ptolemaic''
41 * approximation; both the Earth's spin and orbit are included.
42 *
43 * ### Description ###
44 *
45 * This function computes metric components in a way that yields results
46 * very similar to those of LALCoherentMetric() called with the
47 * output of LALTBaryPtolemaic(). The CPU demand, however, is less,
48 * and the metric components can be expressed analytically, lending
49 * themselves to better understanding of the behavior of the parameter
50 * space. For short durations (less than about 70000 seconds or 20 hours) a
51 * Taylor series expansion is used to improve the accuracy with which several
52 * terms are computed.
53 *
54 * ### Algorithm ###
55 *
56 * For speed and checking reasons, a minimum of numerical computation is
57 * involved. The metric components can be expressed analytically (though not
58 * tidily) in terms of trig functions and are much too large to be worth
59 * writing down here. More comprehensive documentation on the derivation of
60 * the metric components can be found in the pulgroup CVS archive as
61 * docs/S2/FDS/Isolated/ptolemetric.tex. Jones, Owen, and Whitbeck will write
62 * up the calculation and some tests as a journal article.
63 *
64 * The function XLALGetEarthTimes() is used to calculate the spin and
65 * rotational phase of the Earth at the beginning of the observation.
66 *
67 * On output, the \a metric->data is arranged with the same indexing
68 * scheme as in LALCoherentMetric(). The order of the parameters is
69 * \f$ (f_0, \alpha, \delta) \f$ .
70 *
71 * ### Notes ###
72 *
73 * The analytic metric components were derived separately by Jones and
74 * Whitbeck (and partly by Owen) and found to agree. Also, the output of this
75 * function has been compared against that of the function combination
76 * (CoherentMetric + TDBaryPtolemaic), which is a numerical implementation of
77 * the Ptolemaic approximation, and found to agree up to the fourth
78 * significant figure or better. Even using DTEphemeris.c for the true
79 * Earth's orbit only causes errors in the metric components of order 10\%,
80 * with (so far) no noticeable effect on the sky coverage.
81 *
82 * At present, only one spindown parameter can be included with the sky
83 * location. The code contains (commented out) expressions for
84 * spindown-spindown metric components for an arbitrary number of spindowns,
85 * but the (commented out) spindown-sky components neglect orbital motion.
86 *
87 * A separate routine, XLALSpindownMetric(), has been added to compute the
88 * metric for multiple spindowns but for fixed sky position, suitable for
89 * e.g. directed searches.
90 */
93 PtoleMetricIn *input )
94{
95 INT2 j; /* Loop counters */
96 /*REAL8 temp1, temp2, temp3, temp4; dummy variables */
97 REAL8 R_o, R_s; /* Amplitude of daily/yearly modulation, s */
98 REAL8 lat, lon; /* latitude and longitude of detector site */
99 REAL8 omega_s, omega_o; /* Ang freq of daily/yearly modulation, rad/s */
100 REAL8 phi_o_i; /* Phase of Earth's orbit at begining (epoch) */
101 REAL8 phi_o_f; /* Phase of Earth's orbit at end (epoch+duration) */
102 REAL8 phi_s_i; /* Phase of Earth's spin at beginning (epoch) */
103 REAL8 phi_s_f; /* Phase of Earth's spin at end (epoch+duration) */
104 REAL8 cos_l, sin_l, sin_2l; /* Trig fns for detector lattitude */
105 REAL8 cos_i, sin_i; /* Trig fns for inclination of Earth's spin */
106 REAL8 cos_a, sin_a, sin_2a; /* Trig fns for source RA */
107 REAL8 cos_d, sin_d, sin_2d; /* Trig fns for source declination */
108 REAL8 A[22]; /* Array of intermediate quantities */
109 REAL8 B[10]; /* Array of intermediate quantities */
110 REAL8 Is[5]; /* Array of integrals needed for spindown.*/
111 UINT2 dim; /* Dimension of parameter space */
112 REAL8 tMidnight, tAutumn; /* Needed to calculate phases of spin*/
113 /* and orbit at t_gps =0 */
114 REAL8Vector *big_metric; /* 10-dim metric in (phi,f,a,d,f1) for internal use */
115 REAL8 T; /* Duration of observation */
116 REAL8 f; /* Frequency */
117 /* Some useful short-hand notations involving the orbital phase: */
118 REAL8 D_p_o;
119 REAL8 sin_p_o;
120 REAL8 cos_p_o;
121 REAL8 D_sin_p_o;
122 REAL8 D_cos_p_o;
123 REAL8 D_sin_2p_o;
124 REAL8 D_cos_2p_o;
125 /* Some useful short-hand notations involving the spin phase: */
126 REAL8 D_p_s;
127 REAL8 sin_p_s;
128 REAL8 cos_p_s;
129 REAL8 D_sin_p_s;
130 REAL8 D_cos_p_s;
131 REAL8 D_sin_2p_s;
132 REAL8 D_cos_2p_s;
133 /* Some useful short-hand notations involving spin and orbital phases: */
134 REAL8 D_sin_p_o_plus_s;
135 REAL8 D_sin_p_o_minus_s;
136 REAL8 D_cos_p_o_plus_s;
137 REAL8 D_cos_p_o_minus_s;
138 /* Quantities related to the short-time Tatlor expansions : */
139 REAL8 D_p_o_crit; /* The orbital phase BELOW which series used. */
140 REAL8 sum1, sum2, sum3;
141 REAL8 next1, next2, next3;
142 INT2 j_max; /* Number of terms in series */
143
144
146
147 /* Check for valid input structure. */
148 ASSERT( input != NULL, status, PTOLEMETRICH_ENULL,
150
151 /* Check for valid sky position. */
158 ASSERT( fabs( input->position.latitude ) <= LAL_PI_2, status,
160
161 /* Check for valid maximum frequency. */
164
165 /* Check for valid detector location. */
170
171 if ( input->spindown ) {
172 dim = 2 + input->spindown->length;
173 } else {
174 dim = 2;
175 }
178 ASSERT( metric->data != NULL, status, PTOLEMETRICH_ENULL,
180 ASSERT( metric->length == ( UINT4 )( dim + 1 ) * ( dim + 2 ) / 2, status, PTOLEMETRICH_EDIM,
182
183 /* A bigger metric that includes phase for internal use only: */
184 /* Apart from normalization, this is just the information matrix. */
185 big_metric = NULL;
186 LALDCreateVector( status, &big_metric, ( dim + 2 ) * ( dim + 3 ) / 2 );
187
188 /* Detector location: */
191 cos_l = cos( lat );
192 sin_l = sin( lat );
193 sin_2l = sin( 2 * lat );
194
195 /* Inclination of Earth's spin-axis to ecliptic */
196 sin_i = sin( LAL_IEARTH );
197 cos_i = cos( LAL_IEARTH );
198
199 /* Radii of circular motions in seconds: */
200 R_s = LAL_REARTH_SI / LAL_C_SI;
201 R_o = LAL_AU_SI / LAL_C_SI;
202
203 /* To switch off orbital motion uncomment this: */
204 /* R_o = 0.0; */
205
206 /* To switch off spin motion uncomment this: */
207 /* R_s = 0.0; */
208
209 /* Angular velocities: */
210 omega_s = LAL_TWOPI / LAL_DAYSID_SI;
211 omega_o = LAL_TWOPI / LAL_YRSID_SI;
212
213 /* Duration of observation */
214 T = input->duration;
215
216 /* Frequency: */
217 f = input->maxFreq;
218
219 /* Source RA: */
220 sin_a = sin( input->position.longitude );
221 cos_a = cos( input->position.longitude );
222 sin_2a = sin( 2 * ( input->position.longitude ) );
223
224 /* Source declination: */
225 sin_d = sin( input->position.latitude );
226 cos_d = cos( input->position.latitude );
227 sin_2d = sin( 2 * ( input->position.latitude ) );
228
229 /* Calculation of phases of spin and orbit at start: */
230 XLAL_CHECK_LAL( status, XLALGetEarthTimes( &input->epoch, &tMidnight, &tAutumn ) == XLAL_SUCCESS, XLAL_EFUNC );
231 phi_o_i = -tAutumn / LAL_YRSID_SI * LAL_TWOPI;
232 phi_s_i = -tMidnight / LAL_DAYSID_SI * LAL_TWOPI + lon;
233
234
235 /* Quantities involving the orbital phase: */
236 phi_o_f = phi_o_i + omega_o * T;
237 D_p_o = omega_o * T;
238 sin_p_o = sin( phi_o_f );
239 cos_p_o = cos( phi_o_f );
240 D_sin_p_o = ( sin( phi_o_f ) - sin( phi_o_i ) ) / D_p_o;
241 D_cos_p_o = ( cos( phi_o_f ) - cos( phi_o_i ) ) / D_p_o;
242 D_sin_2p_o = ( sin( 2 * phi_o_f ) - sin( 2 * phi_o_i ) ) / 2.0 / D_p_o;
243 D_cos_2p_o = ( cos( 2 * phi_o_f ) - cos( 2 * phi_o_i ) ) / 2.0 / D_p_o;
244
245 /* Quantities involving the spin phase: */
246 phi_s_f = phi_s_i + omega_s * T;
247 D_p_s = omega_s * T;
248 sin_p_s = sin( phi_s_f );
249 cos_p_s = cos( phi_s_f );
250 D_sin_p_s = ( sin( phi_s_f ) - sin( phi_s_i ) ) / D_p_s;
251 D_cos_p_s = ( cos( phi_s_f ) - cos( phi_s_i ) ) / D_p_s;
252 D_sin_2p_s = ( sin( 2 * phi_s_f ) - sin( 2 * phi_s_i ) ) / 2.0 / D_p_s;
253 D_cos_2p_s = ( cos( 2 * phi_s_f ) - cos( 2 * phi_s_i ) ) / 2.0 / D_p_s;
254
255 /* Some mixed quantities: */
256 D_sin_p_o_plus_s
257 = ( sin( phi_o_f + phi_s_f ) - sin( phi_o_i + phi_s_i ) ) / ( D_p_o + D_p_s );
258 D_sin_p_o_minus_s
259 = ( sin( phi_o_f - phi_s_f ) - sin( phi_o_i - phi_s_i ) ) / ( D_p_o - D_p_s );
260 D_cos_p_o_plus_s
261 = ( cos( phi_o_f + phi_s_f ) - cos( phi_o_i + phi_s_i ) ) / ( D_p_o + D_p_s );
262 D_cos_p_o_minus_s
263 = ( cos( phi_o_f - phi_s_f ) - cos( phi_o_i - phi_s_i ) ) / ( D_p_o - D_p_s );
264
265
266
267 /***************************************************************/
268 /* Small D_p_o overwrite: */
269 /***************************************************************/
270 j_max = 7;
271 D_p_o_crit = 1.4e-2; /* This corresponds to about 70000 seconds */
272
273 sum1 = next1 = D_p_o / 2.0;
274 sum2 = next2 = D_p_o / 3.0 / 2.0;
275 sum3 = next3 = D_p_o;
276
277 for ( j = 1; j <= j_max; j++ ) {
278 next1 *= -pow( D_p_o, 2.0 ) / ( 2.0 * j + 1.0 ) / ( 2.0 * j + 2.0 );
279 sum1 += next1;
280 next2 *= -pow( D_p_o, 2.0 ) / ( 2.0 * j + 2.0 ) / ( 2.0 * j + 3.0 );
281 sum2 += next2;
282 next3 *= -pow( 2.0 * D_p_o, 2.0 ) / ( 2.0 * j + 1.0 ) / ( 2.0 * j + 2.0 );
283 sum3 += next3;
284 }
285
286 if ( D_p_o < D_p_o_crit ) {
287 D_sin_p_o = sin( phi_o_f ) * sum1 + cos( phi_o_f ) * sin( D_p_o ) / D_p_o;
288 D_cos_p_o = cos( phi_o_f ) * sum1 - sin( phi_o_f ) * sin( D_p_o ) / D_p_o;
289 D_sin_2p_o
290 = sin( 2.0 * phi_o_f ) * sum3 + cos( 2.0 * phi_o_f ) * sin( 2.0 * D_p_o ) / 2.0 / D_p_o;
291 D_cos_2p_o
292 = cos( 2.0 * phi_o_f ) * sum3 - sin( 2.0 * phi_o_f ) * sin( 2.0 * D_p_o ) / 2.0 / D_p_o;
293 }
294 /****************************************************************/
295
296
297 /* The A[i] quantities: */
298 A[1] =
299 R_o * D_sin_p_o + R_s * cos_l * D_sin_p_s;
300
301 A[2] =
302 R_o * cos_i * D_cos_p_o + R_s * cos_l * D_cos_p_s;
303
304 A[3] =
305 -R_o * sin_i * D_cos_p_o + R_s * sin_l;
306
307 A[4] =
308 R_o * ( sin_p_o / D_p_o + D_cos_p_o / D_p_o );
309
310 A[5] =
311 R_s * ( sin_p_s / D_p_s + D_cos_p_s / D_p_s );
312
313 A[6] =
314 R_o * ( -cos_p_o / D_p_o + D_sin_p_o / D_p_o );
315
316 /* Special overwrite for A4 and A6: *********************/
317 if ( D_p_o < D_p_o_crit ) {
318 A[4] = R_o * ( cos( phi_o_f ) * sum1 / D_p_o + sin( phi_o_f ) * sum2 );
319 A[6] = R_o * ( sin( phi_o_f ) * sum1 / D_p_o - cos( phi_o_f ) * sum2 );
320 }
321 /***********************************************************/
322
323 A[7] =
324 R_s * ( -cos_p_s / D_p_s + D_sin_p_s / D_p_s );
325
326 A[8] =
327 R_o * R_o * ( 1 + D_sin_2p_o );
328
329 A[9] =
330 R_o * R_s * ( D_sin_p_o_minus_s + D_sin_p_o_plus_s );
331
332 A[10] =
333 R_s * R_s * ( 1 + D_sin_2p_s );
334
335 A[11] =
336 R_o * R_o * D_cos_2p_o;
337
338 A[12] =
339 R_o * R_s * ( -D_cos_p_o_minus_s + D_cos_p_o_plus_s );
340
341 A[13] =
342 R_o * R_s * ( D_cos_p_o_minus_s + D_cos_p_o_plus_s );
343
344 A[14] =
345 R_s * R_s * D_cos_2p_s;
346
347 A[15] =
348 R_o * R_o * ( 1 - D_sin_2p_o );
349
350 A[16] =
351 R_o * R_s * ( D_sin_p_o_minus_s - D_sin_p_o_plus_s );
352
353 A[17] =
354 R_s * R_s * ( 1 - D_sin_2p_s );
355
356 A[18] =
357 R_o * R_s * D_sin_p_o;
358
359 A[19] =
360 R_s * R_s * D_sin_p_s;
361
362 A[20] =
363 R_o * R_s * D_cos_p_o;
364
365 A[21] =
366 R_s * R_s * D_cos_p_s;
367
368
369 /* The B[i] quantities: */
370 B[1] =
371 A[4] + A[5] * cos_l;
372
373 B[2] =
374 A[6] * cos_i + A[7] * cos_l;
375
376 B[3] =
377 A[6] * sin_i + R_s * sin_l / 2;
378
379 B[4] =
380 A[8] + 2 * A[9] * cos_l + A[10] * cos_l * cos_l;
381
382 B[5] =
383 A[11] * cos_i + A[12] * cos_l + A[13] * cos_i * cos_l + A[14] * cos_l * cos_l;
384
385 B[6] =
386 A[15] * cos_i * cos_i + 2 * A[16] * cos_i * cos_l + A[17] * cos_l * cos_l;
387
388 B[7] =
389 -A[11] * sin_i + 2 * A[18] * sin_l - A[13] * sin_i * cos_l + A[19] * sin_2l;
390
391 B[8] =
392 A[15] * sin_i * cos_i - 2 * A[20] * cos_i * sin_l + A[16] * sin_i * cos_l - A[21] * sin_2l;
393
394 B[9] =
395 A[15] * sin_i * sin_i - 4 * A[20] * sin_i * sin_l + 2 * R_s * R_s * sin_l * sin_l;
396
397 /* The spindown integrals. */
398
399 /* orbital t^2 cos */
400
401 Is[1] = ( 2 * sin( phi_o_i ) + 2 * omega_o * T * cos_p_o + ( -2 + pow( omega_o * T, 2 ) ) * sin_p_o ) / pow( omega_o * T, 3 );
402
403 /* spin t^2 cos */
404 Is[2] = ( 2 * sin( phi_s_i ) + 2 * omega_s * T * cos_p_s + ( -2 + pow( omega_s * T, 2 ) ) * sin_p_s ) / pow( omega_s * T, 3 );
405
406 /* orbital t^2 sin */
407 Is[3] = ( -2 * cos( phi_o_i ) + 2 * omega_o * T * sin_p_o - ( -2 + pow( omega_o * T, 2 ) ) * cos_p_o ) / pow( omega_o * T, 3 );
408
409 /*spin t^2 sin */
410
411 Is[4] = ( -2 * cos( phi_s_i ) + 2 * omega_s * T * sin_p_s - ( -2 + pow( omega_s * T, 2 ) ) * cos_p_s ) / pow( omega_s * T, 3 );
412
413
414
415 /* The 4-dim metric components: */
416 /* g_pp = */
417 big_metric->data[0] =
418 1;
419
420 /* g_pf = */
421 big_metric->data[1] =
422 LAL_PI * T;
423
424 /* g_pa = */
425 big_metric->data[3] =
426 -LAL_TWOPI * f * cos_d * ( A[1] * sin_a + A[2] * cos_a );
427
428 /* g_pd = */
429 big_metric->data[6] =
430 LAL_TWOPI * f * ( -A[1] * sin_d * cos_a + A[2] * sin_d * sin_a + A[3] * cos_d );
431
432 /* g_ff = */
433 big_metric->data[2] =
434 pow( LAL_TWOPI * T, 2 ) / 3;
435
436 /* g_fa = */
437 big_metric->data[4] =
438 pow( LAL_TWOPI, 2 ) * f * cos_d * T * ( -B[1] * sin_a + B[2] * cos_a );
439
440 /* g_fd = */
441 big_metric->data[7] =
442 pow( LAL_TWOPI, 2 ) * f * T * ( -B[1] * sin_d * cos_a - B[2] * sin_d * sin_a + B[3] * cos_d );
443
444 /* g_aa = */
445 big_metric->data[5] =
446 2 * pow( LAL_PI * f * cos_d, 2 ) * ( B[4] * sin_a * sin_a + B[5] * sin_2a + B[6] * cos_a * cos_a );
447
448 /* g_ad = */
449 big_metric->data[8] =
450 2 * pow( LAL_PI * f, 2 ) * cos_d * ( B[4] * sin_a * cos_a * sin_d - B[5] * sin_a * sin_a * sin_d
451 - B[7] * sin_a * cos_d + B[5] * cos_a * cos_a * sin_d - B[6] * sin_a * cos_a * sin_d
452 + B[8] * cos_a * cos_d );
453
454 /* g_dd = */
455 big_metric->data[9] =
456 2 * pow( LAL_PI * f, 2 ) * ( B[4] * pow( cos_a * sin_d, 2 ) + B[6] * pow( sin_a * sin_d, 2 )
457 + B[9] * pow( cos_d, 2 ) - B[5] * sin_2a * pow( sin_d, 2 ) - B[8] * sin_a * sin_2d
458 - B[7] * cos_a * sin_2d );
459
460 /*The spindown components*/
461 if ( dim == 3 ) {
462 /* g_p1 = */
463 big_metric->data[10] =
464 T * LAL_PI * f * T / 3;
465
466 /* g_f1= */
467 big_metric->data[11] =
468 T * pow( LAL_PI * T, 2 ) * f / 2;
469
470 /* g_a1 = */
471 big_metric->data[12] = T * 2 * pow( LAL_PI * f, 2 ) * T * ( -cos_d * sin_a * ( R_o * Is[1] + R_s * cos_l * Is[2] ) + cos_d * cos_a * ( R_o * cos_i * Is[3] + R_s * cos_l * Is[4] ) );
472
473 /* g_d1 = */
474 big_metric->data[13] = T * 2 * pow( LAL_PI * f, 2 ) * T * ( -sin_d * cos_a * ( R_o * Is[1] + R_s * cos_l * Is[2] ) - sin_d * sin_a * ( R_o * cos_i * Is[3] + R_s * cos_l * Is[4] ) + cos_d * ( R_o * sin_i * Is[3] + R_s * sin_l / 3 ) );
475
476 /* g_11 = */
477 big_metric->data[14] = T * T * pow( LAL_PI * f * T, 2 ) / 5;
478 }
479
480
481 /**********************************************************/
482 /* Spin-down stuff not consistent with rest of code - don't uncomment! */
483 /* Spindown-spindown metric components, before projection
484 if( input->spindown )
485 for (j=1; j<=dim-2; j++)
486 for (k=1; k<=j; k++)
487 metric->data[(k+2)+(j+2)*(j+3)/2] = pow(LAL_TWOPI*input->maxFreq
488 *input->duration,2)/(j+2)/(k+2)/(j+k+3);
489
490 Spindown-angle metric components, before projection
491 if( input->spindown )
492 for (j=1; j<=(INT4)input->spindown->length; j++) {
493
494 Spindown-RA: 1+(j+2)*(j+3)/2
495 metric->data[1+(j+2)*(j+3)/2] = 0;
496 temp1=0;
497 temp2=0;
498 for (k=j+1; k>=0; k--) {
499 metric->data[1+(j+2)*(j+3)/2] += pow(-1,(k+1)/2)*factrl(j+1)
500 /factrl(j+1-k)/pow(D_p_s,k)*((k%2)?sin_p_s:cos_p_s);
501 metric->data[1+(j+2)*(j+3)/2] += pow(-1,j/2)/pow(D_p_s,j+1)*factrl(j+1)
502 *((j%2)?cos(phi_s_i):sin(phi_s_i));
503 metric->data[1+(j+2)*(j+3)/2] -= (cos_p_s-cos(phi_s_i))/(j+2);
504 metric->data[1+(j+2)*(j+3)/2] *= -pow(LAL_TWOPI*input->maxFreq,2)*R_s*cos_l
505 *cos_d/omega_s/(j+1);
506 temp1+=pow(-1,(k+1)/2)*factrl(j+1)
507 /factrl(j+1-k)/pow(D_p_s,k)*((k%2)?sin_p_s:cos_p_s);
508 temp2+=pow(-1,(k+1)/2)*factrl(j+1)
509 /factrl(j+1-k)/pow(D_p_o,k)*((k%2)?sin_p_o:cos_p_o);
510 }
511 temp1+=pow(-1,j/2)/pow(D_p_s,j+1)*factrl(j+1)
512 *((j%2)?cos(phi_s_i):sin(phi_s_i));
513 temp2+=pow(-1,j/2)/pow(D_p_o,j+1)*factrl(j+1)
514 *((j%2)?cos(phi_o_i):sin(phi_o_i));
515 temp1-=(cos_p_s-cos(phi_s_i))/(j+2);
516 temp2-=(cos_p_o-cos(phi_o_i))/(j+2);
517 temp1*=-pow(LAL_TWOPI*input->maxFreq,2)*R_s*cos_l
518 *cos_d/omega_s/(j+1);
519 temp2*=-pow(LAL_TWOPI*input->maxFreq,2)*R_o*cos_i
520 *cos_d/omega_o/(j+1);
521 metric->data[1+(j+2)*(j+3)/2]+=temp1+temp2;
522 Spindown-dec: 2+(j+2)*(j+3)/2
523 metric->data[2+(j+2)*(j+3)/2] = 0;
524 temp3=0;
525 temp4=0;
526 for (k=j+1; k>=0; k--) {
527 metric->data[2+(j+2)*(j+3)/2] -= pow(-1,k/2)*factrl(j+1)/factrl(j+1-k)
528 /pow(D_p_s,k)*((k%2)?cos_p_s:sin_p_s);
529 metric->data[2+(j+2)*(j+3)/2] += pow(-1,(j+1)/2)/pow(D_p_s,j+1)
530 *factrl(j+1)*((j%2)?sin(phi_s_i):cos(phi_s_i));
531 metric->data[2+(j+2)*(j+3)/2] += (sin_p_s-sin(phi_s_i))/(j+2);
532 metric->data[2+(j+2)*(j+3)/2] *= pow(LAL_TWOPI*input->maxFreq,2)*R_s*cos_l
533 *sin_d/omega_s/(j+1);
534 } for( j... )
535 temp3-=pow(-1,k/2)*factrl(j+1)/factrl(j+1-k)
536 /pow(D_p_s,k)*((k%2)?cos_p_s:sin_p_s);
537 temp4-=pow(-1,k/2)*factrl(j+1)/factrl(j+1-k)
538 /pow(D_p_o,k)*((k%2)?cos_p_o:sin_p_o);
539 }
540 temp3+=pow(-1,(j+1)/2)/pow(D_p_s,j+1)
541 *factrl(j+1)*((j%2)?sin(phi_s_i):cos(phi_s_i));
542 temp4+=pow(-1,(j+1)/2)/pow(D_p_o,j+1)
543 *factrl(j+1)*((j%2)?sin(phi_o_i):cos(phi_o_i));
544 temp3+=(sin_p_s-sin(phi_s_i))/(j+2);
545 temp4+=(sin_p_o-sin(phi_o_i))/(j+2);
546 temp3*=pow(LAL_TWOPI*input->maxFreq,2)*R_s*cos_l
547 *sin_d/omega_s/(j+1);
548 temp4*=pow(LAL_TWOPI*input->maxFreq,2)*R_s*cos_i
549 *sin_d/omega_o/(j+1);
550 metric->data[2+(j+2)*(j+3)/2]=temp3+temp4;
551 }
552 f0-spindown : 0+(j+2)*(j+3)/2
553 if( input->spindown )
554 for (j=1; j<=dim-2; j++)
555 metric->data[(j+2)*(j+3)/2] = 2*pow(LAL_PI,2)*input->maxFreq
556 *pow(input->duration,2)/(j+2)/(j+3);*/
557 /*************************************************************/
558
559
560 /* Project down to 4-dim metric: */
561
562 /*f-f component */
563 metric->data[0] = big_metric->data[2]
564 - big_metric->data[1] * big_metric->data[1] / big_metric->data[0];
565 /*f-a component */
566 metric->data[1] = big_metric->data[4]
567 - big_metric->data[1] * big_metric->data[3] / big_metric->data[0];
568 /*a-a component */
569 metric->data[2] = big_metric->data[5]
570 - big_metric->data[3] * big_metric->data[3] / big_metric->data[0];
571 /*f-d component */
572 metric->data[3] = big_metric->data[7]
573 - big_metric->data[6] * big_metric->data[1] / big_metric->data[0];
574 /*a-d component */
575 metric->data[4] = big_metric->data[8]
576 - big_metric->data[6] * big_metric->data[3] / big_metric->data[0];
577 /*d-d component */
578 metric->data[5] = big_metric->data[9]
579 - big_metric->data[6] * big_metric->data[6] / big_metric->data[0];
580 if ( dim == 3 ) {
581
582 /*f-f1 component */
583 metric->data[6] = big_metric->data[11]
584 - big_metric->data[1] * big_metric->data[10] / big_metric->data[0];
585
586 /*a-f1 component */
587 metric->data[7] = big_metric->data[12]
588 - big_metric->data[3] * big_metric->data[10] / big_metric->data[0];
589
590 /*d-f1 component */
591 metric->data[8] = big_metric->data[13]
592 - big_metric->data[6] * big_metric->data[10] / big_metric->data[0];
593
594 /* f1-f1 component */
595 metric->data[9] = big_metric->data[14]
596 - big_metric->data[10] * big_metric->data[10] / big_metric->data[0];
597 }
598
599 LALDDestroyVector( status, &big_metric );
600 /* All done */
601 RETURN( status );
602} /* LALPtoleMetric() */
603
604
605/* This is a dead simple, no error-checking, private factorial function. */
606/* static int factrl( int arg ) */
607/* { */
608/* int ans = 1; */
609
610/* if (arg==0) return 1; */
611/* do { */
612/* ans *= arg; */
613/* } */
614/* while(--arg>0); */
615/* return ans; */
616/* } */ /* factrl() */
617
618
619/**
620 * \brief Unified "wrapper" to provide a uniform interface to LALPtoleMetric() and LALCoherentMetric().
621 * \author Reinhard Prix
622 *
623 * The parameter structure of LALPtoleMetric() was used, because it's more compact.
624 */
627 PtoleMetricIn *input )
628{
629 UINT4 nSpin, dim;
630
631 INITSTATUS( stat );
633
637
638 if ( input->spindown ) {
639 nSpin = input->spindown->length;
640 } else {
641 nSpin = 0;
642 }
643
644
645 /* allocate the output-metric */
646 dim = 3 + nSpin; /* dimensionality of parameter-space: Alpha,Delta,f + spindowns */
647
648 TRY( LALDCreateVector( stat->statusPtr, metric, dim * ( dim + 1 ) / 2 ), stat );
649
650 switch ( input->metricType ) {
651 case LAL_PMETRIC_COH_PTOLE_ANALYTIC: /* use Ben&Ian's analytic ptolemaic metric */
652 LALPtoleMetric( stat->statusPtr, *metric, input );
653 BEGINFAIL( stat ) {
654 LALDDestroyVector( stat->statusPtr, metric );
655 }
656 ENDFAIL( stat );
657 break;
658
659 default:
660 XLALPrintError( "Unknown metric type `%d`\n", input->metricType );
662 break;
663
664 } /* switch type */
665
667 RETURN( stat );
668
669} /* LALPulsarMetric() */
670
671
672/**
673 * \brief Project out the zeroth dimension of a metric.
674 * \author Creighton, T. D.
675 * \date 2000
676 *
677 * ### Description ###
678 *
679 * This function takes a metric \f$ g_{\alpha\beta} \f$ , where
680 * \f$ \alpha,\beta=0,1,\ldots,n \f$ , and computes the projected metric
681 * \f$ \gamma_{ij} \f$ on the subspace \f$ i,j=1,\ldots,n \f$ , as described in the
682 * header StackMetric.h.
683 *
684 * The argument \a *metric stores the metric components in the manner
685 * used by the functions LALCoherentMetric() and
686 * LALStackMetric(), and \a errors indicates whether error
687 * estimates are included in \a *metric. Thus \a *metric is a
688 * vector of length \f$ (n+1)(n+2)/2 \f$ if \a errors is zero, or of length
689 * \f$ (n+1)(n+2) \f$ if \a errors is nonzero; see LALCoherentMetric()
690 * for the indexing scheme.
691 *
692 * Upon return, \a *metric stores the components of \f$ \gamma_{ij} \f$ in
693 * the same manner as above, with the physically meaningless components
694 * \f$ \gamma_{\alpha0} = \gamma_{0\alpha} \f$ (and their uncertainties) set
695 * identically to zero.
696 *
697 * ### Algorithm ###
698 *
699 * The function simply implements \eqref{eq_gij_gab} in
700 * StackMetric.h. The formula used to convert uncertainties
701 * \f$ s_{\alpha\beta} \f$ in the metric components \f$ g_{\alpha\beta} \f$ into
702 * uncertainties \f$ \sigma_{ij} \f$ in \f$ \gamma_{ij} \f$ is:
703 * \f[
704 * \sigma_{ij} = s_{ij}
705 * + s_{0i}\left|\frac{g_{0j}}{g_{00}}\right|
706 * + s_{0j}\left|\frac{g_{0i}}{g_{00}}\right|
707 * + s_{00}\left|\frac{g_{0i}g_{0j}}{(g_{00})^2}\right| \; .
708 * \f]
709 * Note that if the metric is highly degenerate, one may find that one or
710 * more projected components are comparable in magnitude to their
711 * estimated numerical uncertainties. This can occur when the
712 * observation times are very short or very long compared to the
713 * timescales over which the timing derivatives are varying. In the
714 * former case, one is advised to use analytic approximations or a
715 * different parameter basis. In the latter case, the degenerate
716 * components are often not relevant for data analysis, and can be
717 * effectively set to zero.
718 *
719 * Technically, starting from a full metric
720 * \f$ g_{\alpha\beta}(\mathbf{\lambda}) \f$ , the projection
721 * \f$ \gamma_{ij}(\vec\lambda) \f$ is the metric of a subspace
722 * \f$ \{\vec\lambda\} \f$ passing through the point \f$ \mathbf{\lambda} \f$ on a plane
723 * orthogonal to the \f$ \lambda^0 \f$ axis. In order for \f$ \gamma_{ij} \f$ to
724 * measure the \em maximum distance between points \f$ \vec\lambda \f$ , it
725 * is important to evaluate \f$ g_{\alpha\beta} \f$ at the value of \f$ \lambda^0 \f$
726 * that gives the largest possible separations. For the pulsar search
727 * formalism discussed in StackMetric.h, this is always
728 * achieved by choosing the largest value of \f$ \lambda^0=f_\mathrm{max} \f$
729 * that is to be covered in the search.
730 */
731void
733{
734 UINT4 s; /* The number of parameters before projection. */
735 UINT4 i, j; /* Indecies. */
736 REAL8 *data; /* The metric data array. */
737
738 INITSTATUS( stat );
739
740 /* Check that data exist. */
743 data = metric->data;
744
745 /* Make sure the metric's length is compatible with some
746 dimensionality s. */
747 for ( s = 0, i = 1; i < metric->length; s++ ) {
748 i = s * ( s + 1 );
749 if ( !errors ) {
750 i = i >> 1;
751 }
752 }
753 s--; /* counteract the final s++ */
754 ASSERT( i == metric->length, stat, PTOLEMETRICH_EPARM,
756
757 /* Now project out the zeroth component of the metric. */
758 for ( i = 1; i < s; i++ )
759 for ( j = 1; j <= i; j++ ) {
760 INT4 i0 = ( i * ( i + 1 ) ) >> 1;
761 INT4 myj0 = ( j * ( j + 1 ) ) >> 1;
762 INT4 ij = i0 + j;
763 if ( errors ) {
764 data[2 * ij] -= data[2 * i0] * data[2 * myj0] / data[0];
765 data[2 * ij + 1] += data[2 * i0 + 1] * fabs( data[2 * myj0] / data[0] )
766 + data[2 * myj0 + 1] * fabs( data[2 * i0] / data[0] )
767 + data[1] * fabs( data[2 * i0] / data[0] ) * fabs( data[2 * myj0] / data[0] );
768 } else {
769 data[ij] -= data[i0] * data[myj0] / data[0];
770 }
771 }
772
773 /* Set all irrelevant metric coefficients to zero. */
774 for ( i = 0; i < s; i++ ) {
775 INT4 i0 = i * ( i + 1 ) >> 1;
776 if ( errors ) {
777 data[2 * i0] = data[2 * i0 + 1] = 0.0;
778 } else {
779 data[i0] = 0.0;
780 }
781 }
782
783 /* And that's it! */
784 RETURN( stat );
785}
786
787
788/**
789 * \brief Figure out dimension of a REAL8Vector -encoded metric (see PMETRIC_INDEX() ).
790 * Return error if input-vector is NULL or not consistent with a quadratic matrix.
791 */
792int
794{
795 UINT4 dim;
796 UINT4 length;
797 UINT4 trylength;
798
799 if ( !metric ) {
800 XLALPrintError( "\nNULL Input received!\n\n" );
802 }
803
804 length = metric->length;
805 if ( length == 0 ) {
806 return 0;
807 }
808
809 dim = 1;
810 while ( ( trylength = dim * ( dim + 1 ) / 2 ) <= length ) {
811 if ( length == trylength ) {
812 return dim;
813 } else {
814 dim ++;
815 }
816 }
817
818 /* no fitting dimension found ==> error */
819 XLALPrintError( "\nInput vector is inconsisten with symmetric quadratic matrix!\n\n" );
821
822}/* XLALFindMetricDim() */
823
824/**
825 * Frequency and frequency derivative components of the metric, suitable for a directed
826 * search with only one fixed sky position. The units are those expected by ComputeFstat.
827 */
829 gsl_matrix *metric, /**< [in] Matrix containing the metric */
830 double Tspan /**< [in] Time span of the data set */
831)
832{
833
834 // Check input
835 XLAL_CHECK( metric != NULL, XLAL_EFAULT );
836 XLAL_CHECK( metric->size1 == metric->size2, XLAL_ESIZE );
838
839 // Calculate metric
840 for ( size_t i = 0; i < metric->size1; ++i ) {
841 for ( size_t j = i; j < metric->size2; ++j ) {
842 gsl_matrix_set( metric, i, j, (
843 4.0 * LAL_PI * LAL_PI * pow( Tspan, i + j + 2 ) * ( i + 1 ) * ( j + 1 )
844 ) / (
845 LAL_FACT[i + 1] * LAL_FACT[j + 1] * ( i + 2 ) * ( j + 2 ) * ( i + j + 3 )
846 ) );
847 gsl_matrix_set( metric, j, i, gsl_matrix_get( metric, i, j ) );
848 }
849 }
850
851 return XLAL_SUCCESS;
852
853} // XLALSpindownMetric
int j
#define ABORT(statusptr, code, mesg)
#define XLAL_CHECK_LAL(sp, assertion,...)
#define ENDFAIL(statusptr)
#define TRY(func, statusptr)
#define ATTATCHSTATUSPTR(statusptr)
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
#define BEGINFAIL(statusptr)
#define MIN_MAXFREQ
Definition: PtoleMetric.c:32
UINT2 A
Definition: SFTnaming.c:46
UINT2 B
Definition: SFTnaming.c:47
static const UINT8 LAL_FACT[]
int XLALGetEarthTimes(const LIGOTimeGPS *tepoch, REAL8 *tMidnight, REAL8 *tAutumn)
This function takes a GPS time from tepoch and uses it to assign tAutumn and tMidnight,...
Definition: GetEarthTimes.c:76
#define LAL_PI_2
#define LAL_IEARTH
#define LAL_DAYSID_SI
#define LAL_PI
#define LAL_YRSID_SI
#define LAL_TWOPI
unsigned char BOOLEAN
double REAL8
int16_t INT2
uint16_t UINT2
uint32_t UINT4
int32_t INT4
#define PTOLEMETRICH_MSGEPARM
Definition: PtoleMetric.h:87
#define PTOLEMETRICH_EDIM
Definition: PtoleMetric.h:82
#define PTOLEMETRICH_MSGEMETRIC
Definition: PtoleMetric.h:90
#define PTOLEMETRICH_MSGENONULL
Definition: PtoleMetric.h:89
void LALPtoleMetric(LALStatus *status, REAL8Vector *metric, PtoleMetricIn *input)
Computes metric components for a pulsar search in the `‘Ptolemaic’' approximation; both the Earth's s...
Definition: PtoleMetric.c:91
#define PTOLEMETRICH_ENULL
Definition: PtoleMetric.h:80
void LALProjectMetric(LALStatus *stat, REAL8Vector *metric, BOOLEAN errors)
Project out the zeroth dimension of a metric.
Definition: PtoleMetric.c:732
#define PTOLEMETRICH_EPARM
Definition: PtoleMetric.h:81
#define PTOLEMETRICH_MSGEDIM
Definition: PtoleMetric.h:88
#define PTOLEMETRICH_EMETRIC
Definition: PtoleMetric.h:84
int XLALSpindownMetric(gsl_matrix *metric, double Tspan)
Frequency and frequency derivative components of the metric, suitable for a directed search with only...
Definition: PtoleMetric.c:828
#define PTOLEMETRICH_MSGENULL
Definition: PtoleMetric.h:86
#define PTOLEMETRICH_ENONULL
Definition: PtoleMetric.h:83
void LALPulsarMetric(LALStatus *stat, REAL8Vector **metric, PtoleMetricIn *input)
Unified "wrapper" to provide a uniform interface to LALPtoleMetric() and LALCoherentMetric().
Definition: PtoleMetric.c:625
int XLALFindMetricDim(const REAL8Vector *metric)
Figure out dimension of a REAL8Vector -encoded metric (see PMETRIC_INDEX() ).
Definition: PtoleMetric.c:793
@ LAL_PMETRIC_COH_PTOLE_ANALYTIC
Definition: PtoleMetric.h:97
COORDINATESYSTEM_EQUATORIAL
void LALDCreateVector(LALStatus *, REAL8Vector **, UINT4)
void LALDDestroyVector(LALStatus *, REAL8Vector **)
#define XLAL_ERROR(...)
#define XLAL_CHECK(assertion,...)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_ESIZE
XLAL_EINVAL
float data[BLOCKSIZE]
Definition: hwinject.c:360
T
LALFrDetector frDetector
REAL8 vertexLongitudeRadians
REAL8 vertexLatitudeRadians
This structure will likely be changed to match up better with those under StackMetric....
Definition: PtoleMetric.h:110
SkyPosition position
The equatorial coordinates at which the metric components are evaluated.
Definition: PtoleMetric.h:111
REAL4Vector * spindown
The (dimensionless) spindown parameters for which the metric components are evaluated.
Definition: PtoleMetric.h:112
REAL4 maxFreq
The maximum frequency to be searched, in Hz.
Definition: PtoleMetric.h:115
LALPulsarMetricType metricType
The type of metric to use: analytic, Ptolemaic or fully ephemeris-based.
Definition: PtoleMetric.h:118
const LALDetector * site
The detector site, used only for its latitude and longitude.
Definition: PtoleMetric.h:116
REAL4 duration
Duration of integration, in seconds.
Definition: PtoleMetric.h:114
LIGOTimeGPS epoch
When the coherent integration begins.
Definition: PtoleMetric.h:113
REAL8 * data
REAL8 longitude
REAL8 latitude
CoordinateSystem system