Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALInspiral 5.0.3.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
InspiralSpinBank.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Chad Hanna, Gareth Jones, Jolien Creighton, Benjamin Owen
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/AVFactories.h>
22#include <lal/LALConfig.h>
23#include <lal/LALConstants.h>
24#include <lal/LALDatatypes.h>
25#include <lal/LALInspiralBank.h>
26#include <lal/LALMalloc.h>
27#include <lal/LALStatusMacros.h>
28#include <lal/LALStdlib.h>
29#include <lal/LIGOMetadataTables.h>
30#include <lal/MatrixUtils.h>
31#include <lal/SeqFactories.h>
32
33#ifdef __GNUC__
34#define UNUSED __attribute__ ((unused))
35#else
36#define UNUSED
37#endif
38
39#define INSPIRALSPINBANKC_ENOTILES 5
40#define INSPIRALSPINBANKC_MSGENOTILES "No templates were generated"
41
42/* Internal structures and functions --------------------------------------- */
43
44static void cleanup(LALStatus *,
45 REAL4Array **,
46 UINT4Vector **,
47 REAL4Vector **,
50 INT4 *
51 ); /* cleanup() prototype */
52
53static REAL4 calculateX(
54 REAL4,
55 REAL4,
56 REAL4,
57 REAL4,
58 REAL4,
59 REAL4,
60 INT4,
61 REAL4
62 ); /* calculateX() prototype */
63
64static REAL4 calculateY(
65 REAL4,
66 REAL4,
67 REAL4,
68 REAL4,
69 REAL4,
70 REAL4,
71 INT4,
72 REAL4
73 ); /* calculateY() prototype */
74
75static REAL4 calculateZ(
76 REAL4,
77 REAL4,
78 REAL4
79 ); /* calculateZ() prototype */
80
81static INT4 test(
82 REAL4,
83 REAL4,
84 REAL4,
85 REAL4,
86 REAL4,
87 REAL4,
88 REAL4,
89 REAL4
90 ); /* test() prototype */
91
92static BOOLEAN inPsiRegion(
93 REAL4,
94 REAL4,
95 REAL4,
97 REAL4
98);
99
100/* END - Internal structures and functions --------------------------------- */
101
102
103/* LALINSPIRALSPINBANKMETRIC() --------------------------------------------- */
104static void
107 REAL4Array *metric,
108 InspiralMomentsEtc *moments,
109 InspiralTemplate *inspiralTemplate,
110 REAL4 *f0
111 )
112{
113 INT4 loop = 0;
114 REAL8 J1 = 0.0;
115 REAL8 J4 = 0.0;
116 REAL8 J6 = 0.0;
117 REAL8 J9 = 0.0;
118 REAL8 J11 = 0.0;
119 REAL8 J12 = 0.0;
120 REAL8 J14 = 0.0;
121 REAL8 J17 = 0.0;
122
125
126 if (!metric){
127 ABORT(status, LALINSPIRALBANKH_ENULL, LALINSPIRALBANKH_MSGENULL);
128 }
129 if (!moments){
130 ABORT(status, LALINSPIRALBANKH_ENULL, LALINSPIRALBANKH_MSGENULL);
131 }
132
133
134 /* Rescale the moments to F0 = Noise Curve Minimum */
135 for(loop = 1; loop <=17; loop++){
136 moments->j[loop] *= pow((inspiralTemplate->fLower/(*f0)), ((7.0-(REAL4) loop)/3.0));
137 }
138
139/* This just copies the noise moment data from *moments */
140 J1 = moments->j[1];
141 J4 = moments->j[4];
142 J6 = moments->j[6];
143 J9 = moments->j[9];
144 J11 = moments->j[11];
145 J12 = moments->j[12];
146 J14 = moments->j[14];
147 J17 = moments->j[17];
148
149 /* Set metric components as functions of moments. */
150
151 metric->data[0] = (REAL4) 0.5*(J17-J12*J12-(J9-J4*J12)*(J9-J4*J12)/(J1-J4*J4));
152 metric->data[1] = (REAL4) 0.5*(J14-J9*J12-(J6-J4*J9)*(J9-J4*J12)/(J1-J4*J4));
153 metric->data[2] = (REAL4) 0;
154 metric->data[3] = (REAL4) 0.5*(J14-J9*J12-(J6-J4*J9)*(J9-J4*J12)/(J1-J4*J4));
155 metric->data[4] = (REAL4) 0.5*(J11-J9*J9-(J6-J4*J9)*(J6-J4*J9)/(J1-J4*J4));
156
157 metric->data[5] = (REAL4) 0.0;
158 metric->data[6] = (REAL4) 0.0;
159 metric->data[7] = (REAL4) 0.0;
160 metric->data[8] = (REAL4) 0.5*(J11-J9*J9-(J6-J4*J9)*(J6-J4*J9)/(J1-J4*J4));
161
162 /* Say it if we're asked to. */
163 if ( lalDebugLevel & LALINFO )
164 {
165 CHAR msg[256];
166 snprintf( msg, XLAL_NUM_ELEM(msg), "metric components:\n"
167 "psi0-psi0 %e\npsi0-psi3 %e psi3-psi3 %e\npsi0-beta %e "
168 "psi3-beta %e beta-beta %e\n", metric->data[0] /
169 pow(*f0,10./3), metric->data[3] / pow(*f0,7./3),
170 metric->data[4] / pow(*f0,4./3), metric->data[6] /
171 pow(*f0,7./3), metric->data[7] / pow(*f0,4./3),
172 metric->data[8] / pow(*f0,4./3) );
173 LALInfo( status, msg );
174 snprintf( msg, XLAL_NUM_ELEM(msg), "f0 = %f j1=%f j4=%f "
175 "j6=%f j9=%f j11=%f j12=%f j14=%f j17=%f", *f0, J1, J4,
176 J6, J9, J11, J12, J14, J17 );
177 LALInfo( status, msg );
178 }
179
181 RETURN( status );
182} /* LALInspiralSpinBankMetric */
183
184
185/* Allocate a template at these coordinate values. */
186/* Does no error checking, so check immediately after calling. */
187static void
189 REAL4 x,
190 REAL4 y,
191 REAL4 z,
192 REAL4 f0,
193 SnglInspiralTable **tmplt,
194 INT4 *ntiles,
195 BOOLEAN havePsi )
196{
197 REAL4 mass, eta, m1, m2;
198
199 *tmplt = (*tmplt)->next = (SnglInspiralTable *) LALCalloc( 1,
200 sizeof(SnglInspiralTable) );
201
202 mass = -y/x / (16.0*LAL_PI*LAL_PI*f0);
203 eta = 16.0457 * pow( -x*x/y/y/y/y/y, 0.3333333 );
204 m1 = 0.5*mass* (1 + sqrt(1 - 4*eta));
205 m2 = 0.5*mass* (1 - sqrt(1 - 4*eta));
206
207 if ( ! havePsi )
208 {
209 (*tmplt)->mass1 = m1;
210 (*tmplt)->mass2 = m2;
211 (*tmplt)->eta = eta;
212 (*tmplt)->mchirp = pow(m1*m2,0.6)/pow(m1+m2,0.2);
213 }
214 (*tmplt)->psi0 = x*pow(f0,5./3);
215 (*tmplt)->psi3 = y*pow(f0,2./3);
216 (*tmplt)->beta = z*pow(f0,2./3);
217 ++(*ntiles);
218} /* allocate() */
219
220
221/**
222 * \ingroup LALInspiralBank_h
223 * \author Hanna, C. R. and Owen, B. J.
224 * \brief This function creates a bank of BCVSpin templates to search for precessing binaries.
225 *
226 * ### Algorithm ###
227 *
228 * The code checks <tt>coarseIn->mMin</tt> to determine whether the limits on
229 * the target region are in terms of masses or phenomenological parameters.
230 * A positive value indicates that mass limits are being used.
231 *
232 * If mass limits are used, the target region of parameter space is a
233 * distorted box in the coordinates \f$(x=\psi_0, y=\psi_3, z=\beta)\f$. The
234 * metric at high values of \f$\beta\f$ is constant. It is convenient to rotate
235 * to coordinates \f$(x',y',z')\f$ which lie along eigenvectors of the metric.
236 *
237 * The algorithm first draws a rectilinear box in the primed coordinates
238 * which includes the target region, then steps through along the
239 * directions of the primed coordinates. At each point it tests if the
240 * point lies within the target region. If the point is inside the target
241 * region, the algorithm adds a template to the linked list. If not, it
242 * continues through the box containing the target region.
243 *
244 * The tiling is done with a body-centered cubic lattice. People usually
245 * solve the non-overlapping bcc problem rather than the overlapping one
246 * here, so it's worth mentioning how we do it. I don't have time to stick
247 * in the 3D figures you need to show it properly, but you can figure out
248 * the spacing by finding the smallest sphere that contains the
249 * Wigner-Seitz cell. When you do that you find that the lattice constant
250 * (spacing between templates in the plane, in proper distance) is
251 * \f$(4/3)\sqrt{2\mu}\f$. So the coordinate spacing is that divided by the
252 * square root of the corresponding eigenvalue of the metric. (The vertical
253 * spacing in the bcc lattice is multiplied by a further 1/2.)
254 *
255 * If \f$(\psi_0, \psi_3, \beta)\f$ limits are used, the tiling is done in the
256 * given box with a bcc lattice.
257 *
258 * ### Notes ###
259 *
260 * Currently we use a static function for the metric based on an
261 * approximation that is good only for large \f$\beta\f$. We should update it
262 * and put it out in the LAL namespace.
263 *
264 * The metric relies on approximations that make it valid only for a binary
265 * system with a total mass \f$<15M\odot\f$ where the larger body's minimum mass
266 * is at least twice the smaller body's maximum mass. If the parameter
267 * range is specified with physical parameters rather than the
268 * phenomenological parameters \f$(\psi_0, \psi_3, \beta)\f$ then using mass
269 * values that violate these conditions will result in an error message.
270 *
271 */
272void
275 SnglInspiralTable **tiles,
276 INT4 *ntiles,
277 InspiralCoarseBankIn *coarseIn
278 )
279
280{
281 SnglInspiralTable *tmplt = NULL; /* loop counter */
282 REAL4Array *metric = NULL; /* parameter-space metric */
283 UINT4Vector *metricDimensions = NULL; /* contains the dimension of metric */
284 REAL4Vector *eigenval = NULL; /* eigenvalues of metric */
285 InspiralMomentsEtc moments; /* Added for LALGetInspiralMoments() */
286 InspiralTemplate inspiralTemplate; /* Added for LALGetInspiralMoments() */
287 REAL4 x, y, z; /* psi0, psi3, beta coordinates */
288 REAL4 x0, myy0, z0; /* minimum values of x, y, z */
289 REAL4 x1, myy1, z1; /* maximum values of x, y, z */
290 REAL4 xp, yp, zp; /* metric eigenvector coordinates */
291 REAL4 xp0, yp0, UNUSED zp0; /* minimum values of xp, yp, zp */
292 REAL4 xp1, yp1, zp1; /* maximum values of xp, yp, zp */
293 REAL4 dxp, dyp, dzp; /* step sizes in xp, yp, zp */
294 REAL4 theta; /* angle of rotation for xp and yp */
295 REAL4 m1Min=0, m1Max=0; /* range of m1 to search */
296 REAL4 m2Min=0, m2Max=0; /* range of m2 to search */
297 REAL4 f0 = -1; /* frequency of minimum of noise curve */
298 INT2 bccFlag = 0; /* determines offset for bcc tiling */
299 INT4 cnt = 0; /* loop counter set to value of ntiles */
300 REAL8 shf0 = 1; /* used to find minimum of shf */
301 BOOLEAN havePsi; /* are we using phenom parameters? */
302
303 /* Set up status pointer. */
306
307
309 LALINSPIRALBANKH_MSGENULL );
310 /* Check that minimal match is OK. */
312 LALINSPIRALBANKH_MSGECHOICE );
313 /* Sanity check parameter bounds. */
314 if( coarseIn->mMin > 0 )
315 {
317 LALINSPIRALBANKH_MSGECHOICE );
318 ASSERT( coarseIn->MMax > 2*coarseIn->mMin, status,
319 LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE );
320 havePsi = 0;
321 }
322 /* Sanity check phenomenological parameter bounds. */
323 else
324 {
326 LALINSPIRALBANKH_MSGECHOICE );
327 ASSERT( coarseIn->psi0Max > coarseIn->psi0Min, status,
328 LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE );
330 LALINSPIRALBANKH_MSGECHOICE );
331 ASSERT( coarseIn->psi3Max > coarseIn->psi3Min, status,
332 LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE );
333 ASSERT( coarseIn->betaMax > coarseIn->betaMin, status,
334 LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE );
335 havePsi = 1;
336 }
337 /* Check that noise curve exists. */
339 LALINSPIRALBANKH_MSGENULL );
341 LALINSPIRALBANKH_MSGENULL );
342
343 /* Allocate memory for 3x3 parameter-space metric & eigenvalues. */
344 LALU4CreateVector( status->statusPtr, &metricDimensions, (UINT4) 2 );
346 cleanup(status->statusPtr, &metric, &metricDimensions, &eigenval, *tiles, tmplt, ntiles);
348 metricDimensions->data[0] = 3;
349 metricDimensions->data[1] = 3;
350 LALSCreateArray( status->statusPtr, &metric, metricDimensions );
352 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt, ntiles);
354 eigenval = NULL;
355 LALSCreateVector( status->statusPtr, &eigenval, 3 );
357 cleanup(status->statusPtr,&metric, &metricDimensions,&eigenval,*tiles,tmplt, ntiles);
359
360 /* Set f0 to frequency of minimum of noise curve. */
361 for( cnt = 0; cnt < (INT4) coarseIn->shf.data->length; cnt++ )
362 {
363 if( coarseIn->shf.data->data[cnt] > 0 && coarseIn->shf.data->data[cnt] <
364 shf0 )
365 {
366 f0 = (REAL4) coarseIn->shf.deltaF * cnt;
367 shf0 = coarseIn->shf.data->data[cnt];
368 }
369 }
370 /* Compute noise moments. */
371 inspiralTemplate.fLower = coarseIn->fLower;
372 inspiralTemplate.fCutoff = coarseIn->fUpper;
373 LALGetInspiralMoments( status->statusPtr, &moments, &(coarseIn->shf),
374 &inspiralTemplate );
376 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
378
379 /* Find the metric. */
380 LALInspiralSpinBankMetric(status->statusPtr, metric, &moments, &inspiralTemplate, &f0);
382 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt, ntiles);
384 /* Find eigenvalues and eigenvectors. */
385 LALSSymmetricEigenVectors( status->statusPtr, eigenval, metric );
387 cleanup(status->statusPtr,&metric, &metricDimensions,&eigenval,*tiles,tmplt, ntiles);
389
390 /* Allocate first template, which will remain blank. */
391 *tiles = tmplt = (SnglInspiralTable *) LALCalloc( 1,
392 sizeof( SnglInspiralTable ) );
393 if ( *tiles == NULL )
394 {
395 cleanup( status->statusPtr, &metric, &metricDimensions, &eigenval,
396 *tiles, tmplt, ntiles);
397 ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
398 }
399 *ntiles = 0;
400
401 /* Set stepsizes from eigenvalues and angle from eigenvectors. */
402 if( eigenval->data[0] <= 0 || eigenval->data[1] <=0 || eigenval->data[2]
403 <= 0 )
404 {
405 ABORT(status, LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE);
406 }
407 dxp = 1.333333*sqrt(2*(1-coarseIn->mmCoarse)/eigenval->data[0]);
408 dyp = 1.333333*sqrt(2*(1-coarseIn->mmCoarse)/eigenval->data[1]);
409 dzp = 0.6666667*sqrt(2*(1-coarseIn->mmCoarse)/eigenval->data[2]);
410 theta = atan2( -metric->data[3], -metric->data[0] );
411printf( "theta is %e\n", theta );
412
413 /* If target region is given in terms of masses... */
414 if ( ! havePsi )
415 {
416 /* Hardcode mass range on higher mass for the moment. */
417 m2Min = coarseIn->mMin*LAL_MTSUN_SI;
418 m2Max = coarseIn->MMax*LAL_MTSUN_SI/2;
419 m1Min = 2.0*m2Max;
420 m1Max = 15.0*LAL_MTSUN_SI - m2Max;
421
422 /* Set box on unprimed phenom coordinates including region. */
423 x0 = 0.9*(3.0/128) / (pow(LAL_PI*f0*(m1Max+m2Max),1.666667)
424 *(m1Max*m2Max/pow(m1Max+m2Max,2)));
425 myy0 = 1.1*(-.375*LAL_PI) / (pow(LAL_PI*f0*(m1Max+m2Min),0.6666667)*(m1Max*m2Min/pow(m1Max+m2Min,2)));
426 z0 = 0;
427 x1 = 1.1*(3.0/128) / (pow(LAL_PI*f0*(m1Min+m2Min),1.666667)*(m1Min*m2Min/pow(m1Min+m2Min,2)));
428 myy1 = .9*(-.375*LAL_PI) / (pow(LAL_PI*f0*(m1Min+m2Max),0.6666667)*(m1Min*m2Max/pow(m1Min+m2Max,2)));
429 z1 = 3.8* LAL_PI/29.961432 * (1+0.75*m2Max/m1Min) * (m1Max/m2Min) * pow(LAL_MTSUN_SI*100.0/(m1Min+m2Min), 0.6666667);
430 }
431 /* Target region is given in terms of psi etc (unprimed). */
432 else
433 {
434 /* Rescale to dimensionless parameters used internally. */
435 x0 = coarseIn->psi0Min / pow( f0, 5./3 );
436 x1 = coarseIn->psi0Max / pow( f0, 5./3 );
437 myy0 = coarseIn->psi3Min / pow( f0, 2./3 );
438 myy1 = coarseIn->psi3Max / pow( f0, 2./3 );
439 z0 = coarseIn->betaMin / pow( f0, 2./3 );
440 z1 = coarseIn->betaMax / pow( f0, 2./3 );
441 }
442
443 /* Set boundaries of bigger box in primed (eigen) coordinates. */
444 xp0 = x0 + sin(theta)*sin(theta) * (x1 - x0);
445 yp0 = myy0 - cos(theta)*sin(theta) * (x1 - x0);
446 yp1 = sin(theta) * (x1 - x0) + cos(theta) * (myy1 - myy0);
447 xp1 = sin(theta) * (myy1 - myy0) + cos(theta) * (x1 - x0);
448 zp0 = z0;
449 zp1 = z1;
450
451 /* This loop generates the template bank. */
452 for (zp = 0; zp <= zp1; zp += dzp)
453 {
454 bccFlag++;
455 for (yp = 0; yp<= yp1; yp += dyp)
456 {
457 for (xp = 0; xp <= xp1; xp += dxp)
458 {
459
460 /* If the point is in the target region, allocate a template. */
461 x = calculateX(0, xp0, xp, dxp, yp, dyp, bccFlag, theta);
462 y = calculateY(0, yp0, xp, dxp, yp, dyp, bccFlag, theta);
463 z = calculateZ(0, zp, dzp);
464 if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
465 || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
466 {
467 allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
468 if( tmplt == NULL )
469 {
470 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
471 ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
472 }
473 }
474
475 /* If dx behind is not in region, try dx/2 behind. */
476 x = calculateX(-1, xp0, xp, dxp, yp, dyp, bccFlag, theta);
477 if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
478 || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
479 {
480 x = calculateX(-0.5, xp0, xp, dxp, yp, dyp, bccFlag, theta);
481 if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
482 || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
483 {
484 allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
485 if( tmplt == NULL )
486 {
487 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
488 ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
489 }
490 }
491 }
492
493 /* If dy behind is not in region, try dy/2 behind. */
494 x = calculateX(0, xp0, xp, dxp, yp, dyp, bccFlag, theta);
495 y = calculateY(-1, yp0, xp, dxp, yp, dyp, bccFlag, theta);
496 if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
497 || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
498 {
499 y = calculateY(-0.5, yp0, xp, dxp, yp, dyp, bccFlag, theta);
500 if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
501 || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
502 {
503 allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
504 if (!tmplt){
505 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
506 ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
507 }
508 }
509 }
510
511 /* If dz behind is not in region, try dz/2 behind. */
512 y = calculateY(0, yp0, xp, dxp, yp, dyp, (bccFlag+1), theta);
513 z = calculateZ(-1, zp, dzp);
514 if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
515 || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
516 {
517 z = calculateZ(-0.5, zp, dzp);
518 if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
519 || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
520 {
521 allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
522 if (!tmplt){
523 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
524 ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
525 }
526 }
527 }
528
529 /* If dx ahead is not in region, try dx/2 ahead. */
530 x = calculateX(1, xp0, xp, dxp, yp, dyp, bccFlag, theta);
531 y = calculateY(0, yp0, xp, dxp, yp, dyp, (bccFlag+1), theta);
532 z = calculateZ(0, zp, dzp);
533 if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
534 || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
535 {
536 x = calculateX(0.5, xp0, xp, dxp, yp, dyp, bccFlag, theta);
537 if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
538 || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
539 {
540 allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
541 if (!tmplt){
542 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
543 ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
544 }
545 }
546 }
547
548 /* If dy ahead is not in region, try dy/2 ahead. */
549 x = calculateX(0, xp0, xp, dxp, yp, dyp, bccFlag, theta);
550 y = calculateY(1, yp0, xp, dxp, yp, dyp, bccFlag, theta);
551 if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
552 || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
553 {
554 y = calculateY(0.5, yp0, xp, dxp, yp, dyp, bccFlag, theta);
555 if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
556 || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
557 {
558 allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
559 if (!tmplt){
560 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
561 ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
562 }
563 }
564 }
565
566 /* If dz ahead is not in region, try dz/2 ahead. */
567 y = calculateY(0, yp0, xp, dxp, yp, dyp, (bccFlag+1), theta);
568 z = calculateZ(1, zp, dzp);
569 if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
570 || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
571 {
572 z = calculateZ(0.5, zp, dzp);
573 if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
574 || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
575 {
576 allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
577 if (!tmplt){
578 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
579 ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
580 }
581 }
582 }
583 } /* for (zp...) */
584 } /* for (yp...) */
585 } /* for (zp...) */
586
587 /* Trim the first template, which was left blank. */
588 tmplt = (*tiles)->next;
589 LALFree( *tiles );
590 *tiles = tmplt;
591
592 /* What if no templates were allocated? ABORT */
593 if (*tiles == NULL)
594 {
595 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
597 }
598
599 /* free memory allocated for the vectors and arrays */
600 cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,NULL,NULL,&cnt);
602 RETURN( status );
603} /* LALInspiralSpinBank() */
604
605
606/* Try to free up memory. */
607static void cleanup(
608 LALStatus *s,
609 REAL4Array **m,
610 UINT4Vector **md,
611 REAL4Vector **e,
614 INT4 *nt)
615{
616 INITSTATUS(s);
618
619 if (m){
620 TRY(LALU4DestroyVector(s->statusPtr,md),s);
621 }
622 if (md){
623 TRY(LALSDestroyVector(s->statusPtr, e),s);
624 }
625 if (e){
626 TRY(LALSDestroyArray(s->statusPtr, m),s);
627 }
628 if (t && f)
629 {
630 t = f;
631 while ((t->next) && (*nt > 0))
632 {
633 f = t;
634 t = t->next;
635 LALFree(f);
636 --(*nt);
637 }/* while(tmplt) */
638 LALFree(t);
639 --(*nt);
640 }
642 RETURN( s );
643}
644
646 REAL4 xp0,
647 REAL4 xp,
648 REAL4 dxp,
649 REAL4 yp,
650 REAL4 dyp,
651 INT4 bccFlag,
652 REAL4 theta)
653 {
654 return xp0 + (n*dxp + xp+dxp/2.0*(bccFlag%2))*cos(theta) -
655 (yp+dyp/2.0*(bccFlag%2))*sin(theta);
656 } /* REAL4 x(); */
657
659 REAL4 yp0,
660 REAL4 xp,
661 REAL4 dxp,
662 REAL4 yp,
663 REAL4 dyp,
664 INT4 bccFlag,
665 REAL4 theta)
666 {
667 return (yp0 + (xp+dxp/2.0*((bccFlag)%2))*sin(theta) +
668 (n*dyp + yp+dyp/2.0*((bccFlag)%2))*cos(theta));
669 } /* REAL4 y(); */
670
672 REAL4 zp,
673 REAL4 dzp)
674 {
675 return (zp + n*dzp);
676 } /* REAL4 z(); */
677
678
679/* Check if we're in physical parameter region. */
680static INT4 test(REAL4 x,
681 REAL4 y,
682 REAL4 z,
683 REAL4 m1Min,
684 REAL4 m1Max,
685 REAL4 m2Min,
686 REAL4 m2Max,
687 REAL4 f0){
688
689 REAL4 mass, eta, m1, m2, betaMax;
690 mass = -y/x / (16.0*LAL_PI*LAL_PI*f0);
691 if (mass < 0)
692 return 0;
693 eta = 16.0457 * pow( -x*x/y/y/y/y/y, 0.3333333 );
694 if (eta > 0.25 || eta < 0)
695 return 0;
696 m1 = 0.5*mass* (1 + sqrt(1 - 4*eta));
697 m2 = 0.5*mass* (1 - sqrt(1 - 4*eta));
698 if (m1 > m1Max || m1 < m1Min || m2 > m2Max || m2 < m2Min)
699 return 0;
700 betaMax = 3.8*LAL_PI/29.961432 * (1+0.75*m2/m1)*(m1/m2) * pow((LAL_MTSUN_SI*100.0/mass),0.6666667);
701 if (z > betaMax)
702 return 0;
703 return 1;
704}
705
706
707/* Check eigencoordinates to see if we're in the target region. Used only
708 * if the parameter range is given as psi's rather than masses.
709 */
711 REAL4 psi3,
712 REAL4 beta,
713 InspiralCoarseBankIn *coarseIn,
714 REAL4 f0 )
715{
716 REAL4 fac1 = pow( f0, 5./3 );
717 REAL4 fac2 = fac1 / f0;
718
719 if ( psi0 < coarseIn->psi0Min/fac1 )
720 return 0;
721 if ( psi0 > coarseIn->psi0Max/fac1 )
722 return 0;
723 if ( psi3 < coarseIn->psi3Min/fac2 )
724 return 0;
725 if ( psi3 > coarseIn->psi3Max/fac2 )
726 return 0;
727 if ( beta < coarseIn->betaMin/fac2 )
728 return 0;
729 if ( beta > coarseIn->betaMax/fac2 )
730 return 0;
731
732 return 1;
733} /* inPsiRegion */
static void cleanup(LALStatus *, REAL4Array **, UINT4Vector **, REAL4Vector **, SnglInspiralTable *, SnglInspiralTable *, INT4 *)
static REAL4 calculateZ(REAL4, REAL4, REAL4)
static BOOLEAN inPsiRegion(REAL4, REAL4, REAL4, InspiralCoarseBankIn *, REAL4)
static INT4 test(REAL4, REAL4, REAL4, REAL4, REAL4, REAL4, REAL4, REAL4)
static void LALInspiralSpinBankMetric(LALStatus *status, REAL4Array *metric, InspiralMomentsEtc *moments, InspiralTemplate *inspiralTemplate, REAL4 *f0)
static void allocate(REAL4 x, REAL4 y, REAL4 z, REAL4 f0, SnglInspiralTable **tmplt, INT4 *ntiles, BOOLEAN havePsi)
static REAL4 calculateY(REAL4, REAL4, REAL4, REAL4, REAL4, REAL4, INT4, REAL4)
static REAL4 calculateX(REAL4, REAL4, REAL4, REAL4, REAL4, REAL4, INT4, REAL4)
#define INSPIRALSPINBANKC_MSGENOTILES
#define INSPIRALSPINBANKC_ENOTILES
#define LALCalloc(m, n)
#define LALFree(p)
#define ABORT(statusptr, code, mesg)
#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)
int s
double e
double theta
void LALSCreateArray(LALStatus *, REAL4Array **, UINT4Vector *)
void LALSDestroyArray(LALStatus *, REAL4Array **)
void LALSSymmetricEigenVectors(LALStatus *stat, REAL4Vector *values, REAL4Array *matrix)
#define LAL_PI
#define LAL_MTSUN_SI
unsigned char BOOLEAN
#define XLAL_NUM_ELEM(x)
double REAL8
int16_t INT2
char CHAR
uint32_t UINT4
int32_t INT4
float REAL4
#define lalDebugLevel
LALINFO
int LALInfo(LALStatus *status, const char *info)
#define LALINSPIRALBANKH_ECHOICE
Invalid choice for an input parameter.
#define LALINSPIRALBANKH_ENULL
Null pointer.
void LALInspiralSpinBank(LALStatus *status, SnglInspiralTable **tiles, INT4 *ntiles, InspiralCoarseBankIn *coarseIn)
This function creates a bank of BCVSpin templates to search for precessing binaries.
void LALGetInspiralMoments(LALStatus *status, InspiralMomentsEtc *moments, REAL8FrequencySeries *psd, InspiralTemplate *params)
#define LALINSPIRALBANKH_EMEM
Memory allocation failure.
static const INT4 m
void LALU4CreateVector(LALStatus *, UINT4Vector **, UINT4)
void LALSDestroyVector(LALStatus *, REAL4Vector **)
void LALU4DestroyVector(LALStatus *, UINT4Vector **)
void LALSCreateVector(LALStatus *, REAL4Vector **, UINT4)
list y
int n
x
Input for choosing a template bank.
REAL8 mMin
minimum mass of components to search for
REAL8FrequencySeries shf
Frequency series containing the PSD.
REAL8 psi3Min
minimum value of the parameter
REAL8 betaMin
UNDOCUMENTED.
REAL8 MMax
alternatively, maximum total mass of binary to search for
REAL8 fUpper
Upper frequency cutoff.
REAL8 fLower
Lower frequency cutoff.
REAL8 psi3Max
maximum value of the parameter
REAL8 mmCoarse
Coarse grid minimal match.
REAL8 betaMax
UNDOCUMENTED.
REAL8 psi0Min
minimum value of the parameter
REAL8 psi0Max
maximum value of the parameter
Parameter structure that holds the moments of the PSD and other useful constants required in the comp...
REAL8 j[18]
The required moments are all computed once and stored in this array; The required moments are from J(...
The inspiral waveform parameter structure containing information about the waveform to be generated.
Definition: LALInspiral.h:205
REAL8 fCutoff
upper frequency cutoff in Hz to be used in generating the waveform; If the last stable orbit frequenc...
Definition: LALInspiral.h:213
REAL8 fLower
lower frequency cutoff of the detector in Hz (input)
Definition: LALInspiral.h:217
REAL4 * data
REAL4 * data
REAL8Sequence * data
REAL8 * data
struct tagSnglInspiralTable * next
UINT4 * data