InspiralSpinBank.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Chad Hanna, Gareth Jones, Jolien Creighton, Benjamin Owen
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /**** <lalVerbatim file="InspiralSpinBankCV">
00021  * Authors: Hanna, C. R. and Owen, B. J.
00022  * $Id: InspiralSpinBank.c,v 1.26 2007/06/08 14:41:42 bema Exp $
00023  **** </lalVerbatim> */
00024 
00025 /**** <lalLaTeX>
00026  *
00027  * \subsection{Module \texttt{InspiralSpinBank.c}}
00028  *
00029  * This module creates a bank of templates to search for precessing
00030  * binaries.
00031  *
00032  * \subsubsection*{Prototypes}
00033  * \input{InspiralSpinBankCP}
00034  * %% \idx{LALInspiralSpinBank()}
00035  *
00036  * \subsubsection*{Description}
00037  *
00038  * This function creates a bank of BCVSpin templates to search for
00039  * precessing binaries.
00040  *
00041  * \subsubsection*{Algorithm}
00042  *
00043  * The code checks \verb@coarseIn->mMin@ to determine whether the limits on
00044  * the target region are in terms of masses or phenomenological parameters.
00045  * A positive value indicates that mass limits are being used.
00046  *
00047  * If mass limits are used, the target region of parameter space is a
00048  * distorted box in the coordinates $(x=\psi_0, y=\psi_3, z=\beta)$. The
00049  * metric at high values of $\beta$ is constant. It is convenient to rotate
00050  * to coordinates $(x',y',z')$ which lie along eigenvectors of the metric.
00051  *
00052  * The algorithm first draws a rectilinear box in the primed coordinates
00053  * which includes the target region, then steps through along the
00054  * directions of the primed coordinates.  At each point it tests if the
00055  * point lies within the target region. If the point is inside the target
00056  * region, the algorithm adds a template to the linked list. If not, it
00057  * continues through the box containing the target region.
00058  *
00059  * The tiling is done with a body-centered cubic lattice. People usually
00060  * solve the non-overlapping bcc problem rather than the overlapping one
00061  * here, so it's worth mentioning how we do it. I don't have time to stick
00062  * in the 3D figures you need to show it properly, but you can figure out
00063  * the spacing by finding the smallest sphere that contains the
00064  * Wigner-Seitz cell. When you do that you find that the lattice constant
00065  * (spacing between templates in the plane, in proper distance) is
00066  * $(4/3)\sqrt{2\mu}$. So the coordinate spacing is that divided by the
00067  * square root of the corresponding eigenvalue of the metric. (The vertical
00068  * spacing in the bcc lattice is multiplied by a further 1/2.)
00069  *
00070  * If $(\psi_0, \psi_3, \beta)$ limits are used, the tiling is done in the
00071  * given box with a bcc lattice.
00072  *
00073  * \subsubsection*{Uses}
00074  *
00075  * \begin{verbatim}
00076  * LALCalloc()
00077  * LALFree()
00078  * LALGetInspiralMoments()
00079  * LALSSymmetricEigenVectors()
00080  * \end{verbatim}
00081  *
00082  * \subsubsection*{Notes}
00083  *
00084  * Currently we use a static function for the metric based on an
00085  * approximation that is good only for large $\beta$. We should update it
00086  * and put it out in the LAL namespace.
00087  *
00088  * The metric relies on approximations that make it valid only for a binary
00089  * system with a total mass $<15M\odot$ where the larger body's minimum mass
00090  * is at least twice the smaller body's maximum mass.  If the parameter
00091  * range is specified with physical parameters rather than the
00092  * phenomenological parameters $(\psi_0, \psi_3, \beta)$ then using mass
00093  * values that violate these conditions will result in an error message.   
00094  *
00095  * \vfill{\footnotesize\input{InspiralSpinBankCV}}
00096  *
00097  **** </lalLaTeX> */
00098 
00099 
00100 #include <math.h>
00101 #include <lal/AVFactories.h>
00102 #include <lal/FlatMesh.h>
00103 #include <lal/LALConfig.h>
00104 #include <lal/LALConstants.h>
00105 #include <lal/LALDatatypes.h>
00106 #include <lal/LALInspiralBank.h>
00107 #include <lal/LALMalloc.h>
00108 #include <lal/LALStatusMacros.h>
00109 #include <lal/LALStdlib.h>
00110 #include <lal/LIGOMetadataTables.h>
00111 #include <lal/MatrixUtils.h>
00112 #include <lal/SeqFactories.h>
00113 
00114 
00115 #define INSPIRALSPINBANKC_ENOTILES 5 
00116 #define INSPIRALSPINBANKC_MSGENOTILES "No templates were generated"
00117 
00118 
00119 NRCSID(INSPIRALSPINBANKC, "$Id: InspiralSpinBank.c,v 1.26 2007/06/08 14:41:42 bema Exp $");
00120 
00121 /* Internal structures and functions --------------------------------------- */
00122 
00123 static void cleanup(LALStatus *,
00124     REAL4Array  **, 
00125     UINT4Vector **, 
00126     REAL4Vector **, 
00127     SnglInspiralTable   *, 
00128     SnglInspiralTable   *,
00129     INT4        *
00130     ); /* cleanup() prototype */
00131 
00132 static REAL4 calculateX(
00133     REAL4,
00134     REAL4,
00135     REAL4,
00136     REAL4,
00137     REAL4,
00138     REAL4,
00139     INT4,
00140     REAL4
00141     ); /* calculateX() prototype */
00142 
00143 static REAL4 calculateY(
00144     REAL4,
00145     REAL4,
00146     REAL4,
00147     REAL4,
00148     REAL4,
00149     REAL4,
00150     INT4,
00151     REAL4
00152     ); /* calculateY() prototype */
00153 
00154 static REAL4 calculateZ(
00155     REAL4,
00156     REAL4,
00157     REAL4
00158     ); /* calculateZ() prototype */
00159 
00160 static INT4 test(
00161     REAL4,
00162     REAL4,
00163     REAL4,
00164     REAL4,
00165     REAL4,
00166     REAL4,
00167     REAL4,
00168     REAL4 
00169     ); /* test() prototype */
00170 
00171 static BOOLEAN inPsiRegion(
00172     REAL4,
00173     REAL4,
00174     REAL4,
00175     InspiralCoarseBankIn *,
00176     REAL4
00177 );
00178 
00179 /* END - Internal structures and functions --------------------------------- */
00180 
00181 
00182 /* LALINSPIRALSPINBANKMETRIC() --------------------------------------------- */
00183 static void
00184 LALInspiralSpinBankMetric(
00185    LALStatus            *status,
00186    REAL4Array           *metric,
00187    InspiralMomentsEtc   *moments,
00188    InspiralTemplate     *inspiralTemplate,
00189    REAL4                *f0
00190    )
00191 {
00192   INT4 loop = 0;
00193   REAL8 J1  = 0.0;
00194   REAL8 J4  = 0.0;
00195   REAL8 J6  = 0.0;
00196   REAL8 J9  = 0.0;
00197   REAL8 J11 = 0.0;
00198   REAL8 J12 = 0.0;
00199   REAL8 J14 = 0.0;
00200   REAL8 J17 = 0.0;
00201 
00202   INITSTATUS( status, "LALInspiralSpinBank", INSPIRALSPINBANKC );
00203   ATTATCHSTATUSPTR( status );
00204 
00205   if (!metric){
00206     ABORT(status, LALINSPIRALBANKH_ENULL, LALINSPIRALBANKH_MSGENULL);
00207     }
00208   if (!moments){
00209     ABORT(status, LALINSPIRALBANKH_ENULL, LALINSPIRALBANKH_MSGENULL);
00210     }
00211   
00212   
00213   /* Rescale the moments to F0 = Noise Curve Minimum */
00214   for(loop = 1; loop <=17; loop++){
00215     moments->j[loop] *= pow((inspiralTemplate->fLower/(*f0)), ((7.0-(REAL4) loop)/3.0));
00216     }
00217 
00218 /* This just copies the noise moment data from *moments */
00219   J1  = moments->j[1];
00220   J4  = moments->j[4];
00221   J6  = moments->j[6];
00222   J9  = moments->j[9];
00223   J11 = moments->j[11];
00224   J12 = moments->j[12];
00225   J14 = moments->j[14];
00226   J17 = moments->j[17];
00227                                                                                                                                                 
00228   /* Set metric components as functions of moments. */
00229 
00230   metric->data[0] = (REAL4) 0.5*(J17-J12*J12-(J9-J4*J12)*(J9-J4*J12)/(J1-J4*J4));
00231   metric->data[1] = (REAL4) 0.5*(J14-J9*J12-(J6-J4*J9)*(J9-J4*J12)/(J1-J4*J4));
00232   metric->data[2] = (REAL4) 0;
00233   metric->data[3] = (REAL4) 0.5*(J14-J9*J12-(J6-J4*J9)*(J9-J4*J12)/(J1-J4*J4));
00234   metric->data[4] = (REAL4) 0.5*(J11-J9*J9-(J6-J4*J9)*(J6-J4*J9)/(J1-J4*J4));
00235 
00236   metric->data[5] = (REAL4) 0.0;
00237   metric->data[6] = (REAL4) 0.0;
00238   metric->data[7] = (REAL4) 0.0;
00239   metric->data[8] = (REAL4) 0.5*(J11-J9*J9-(J6-J4*J9)*(J6-J4*J9)/(J1-J4*J4));
00240 
00241   /* Say it if we're asked to. */
00242   if ( lalDebugLevel & LALINFO )
00243   {
00244     CHAR msg[256];
00245     LALSnprintf( msg, sizeof(msg) / sizeof(*msg), "metric components:\n"
00246                  "psi0-psi0 %e\npsi0-psi3 %e psi3-psi3 %e\npsi0-beta %e "
00247                  "psi3-beta %e beta-beta %e\n", metric->data[0] /
00248                  pow(*f0,10./3), metric->data[3] / pow(*f0,7./3),
00249                  metric->data[4] / pow(*f0,4./3), metric->data[6] /
00250                  pow(*f0,7./3), metric->data[7] / pow(*f0,4./3),
00251                  metric->data[8] / pow(*f0,4./3) );
00252     LALInfo( status, msg );
00253     LALSnprintf( msg, sizeof(msg) / sizeof(*msg), "f0 = %f j1=%f j4=%f "
00254                  "j6=%f j9=%f j11=%f j12=%f j14=%f j17=%f", *f0, J1, J4,
00255                  J6, J9, J11, J12, J14, J17 );
00256     LALInfo( status, msg );
00257   }
00258   
00259   DETATCHSTATUSPTR( status );
00260   RETURN( status );
00261 } /* LALInspiralSpinBankMetric */
00262 
00263 
00264 /* Allocate a template at these coordinate values. */
00265 /* Does no error checking, so check immediately after calling. */
00266 static void
00267 allocate(
00268     REAL4               x,
00269     REAL4               y,
00270     REAL4               z,
00271     REAL4               f0,
00272     SnglInspiralTable **tmplt,
00273     INT4               *ntiles,
00274     BOOLEAN             havePsi )
00275 {
00276   REAL4 mass, eta, m1, m2;
00277 
00278   *tmplt = (*tmplt)->next = (SnglInspiralTable *) LALCalloc( 1,
00279            sizeof(SnglInspiralTable) );
00280 
00281   mass = -y/x / (16.0*LAL_PI*LAL_PI*f0);
00282   eta = 16.0457 * pow( -x*x/y/y/y/y/y, 0.3333333 );
00283   m1 = 0.5*mass* (1 + sqrt(1 - 4*eta));
00284   m2 = 0.5*mass* (1 - sqrt(1 - 4*eta));
00285 
00286   if ( ! havePsi )
00287   {
00288     (*tmplt)->mass1 = m1;
00289     (*tmplt)->mass2 = m2;
00290     (*tmplt)->eta = eta;
00291     (*tmplt)->mchirp = pow(m1*m2,0.6)/pow(m1+m2,0.2);
00292   }
00293   (*tmplt)->psi0 = x*pow(f0,5./3);
00294   (*tmplt)->psi3 = y*pow(f0,2./3);
00295   (*tmplt)->beta = z*pow(f0,2./3);
00296   ++(*ntiles);
00297 } /* allocate() */
00298 
00299 
00300 /* <lalVerbatim file="InspiralSpinBankCP"> */
00301 void
00302 LALInspiralSpinBank(
00303     LALStatus            *status,
00304     SnglInspiralTable   **tiles,
00305     INT4                 *ntiles,
00306     InspiralCoarseBankIn *coarseIn
00307     )
00308 /* </lalVerbatim> */
00309 {
00310   SnglInspiralTable *tmplt =      NULL; /* loop counter */
00311   REAL4Array *metric =            NULL; /* parameter-space metric */
00312   UINT4Vector *metricDimensions = NULL; /* contains the dimension of metric */
00313   REAL4Vector *eigenval =         NULL; /* eigenvalues of metric */
00314   InspiralMomentsEtc moments;           /* Added for LALGetInspiralMoments() */
00315   InspiralTemplate inspiralTemplate;    /* Added for LALGetInspiralMoments() */
00316   REAL4 x, y, z;                        /* psi0, psi3, beta coordinates */
00317   REAL4 x0, myy0, z0;                   /* minimum values of x, y, z */
00318   REAL4 x1, myy1, z1;                   /* maximum values of x, y, z */
00319   REAL4 xp, yp, zp;                     /* metric eigenvector coordinates */
00320   REAL4 xp0, yp0, zp0;                  /* minimum values of xp, yp, zp */
00321   REAL4 xp1, yp1, zp1;                  /* maximum values of xp, yp, zp */
00322   REAL4 dxp, dyp, dzp;                  /* step sizes in xp, yp, zp */
00323   REAL4 theta;                          /* angle of rotation for xp and yp */
00324   REAL4 m1Min, m1Max;                   /* range of m1 to search */
00325   REAL4 m2Min, m2Max;                   /* range of m2 to search */
00326   REAL4 f0 = -1;                        /* frequency of minimum of noise curve */
00327   INT2 bccFlag = 0;                     /* determines offset for bcc tiling */
00328   INT4 cnt = 0;                         /* loop counter set to value of ntiles */
00329   REAL4 shf0 = 1;                       /* used to find minimum of shf */
00330   BOOLEAN havePsi;                      /* are we using phenom parameters?  */
00331   
00332   /* Set up status pointer. */
00333   INITSTATUS( status, "LALInspiralSpinBank", INSPIRALSPINBANKC );
00334   ATTATCHSTATUSPTR( status );
00335   
00336   
00337   ASSERT( coarseIn, status, LALINSPIRALBANKH_ENULL,
00338           LALINSPIRALBANKH_MSGENULL );
00339   /* Check that minimal match is OK. */
00340   ASSERT( coarseIn->mmCoarse > 0, status, LALINSPIRALBANKH_ECHOICE,
00341           LALINSPIRALBANKH_MSGECHOICE );
00342   /* Sanity check parameter bounds. */
00343   if( coarseIn->mMin > 0 )
00344   {
00345     ASSERT( coarseIn->MMax > 0, status, LALINSPIRALBANKH_ECHOICE,
00346             LALINSPIRALBANKH_MSGECHOICE );
00347     ASSERT( coarseIn->MMax > 2*coarseIn->mMin, status,
00348             LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE );
00349     havePsi = 0;
00350   }
00351   /* Sanity check phenomenological parameter bounds. */
00352   else
00353   {
00354     ASSERT( coarseIn->psi0Min > 0, status, LALINSPIRALBANKH_ECHOICE,
00355             LALINSPIRALBANKH_MSGECHOICE );
00356     ASSERT( coarseIn->psi0Max > coarseIn->psi0Min, status,
00357             LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE );
00358     ASSERT( coarseIn->psi3Min < 0, status, LALINSPIRALBANKH_ECHOICE,
00359             LALINSPIRALBANKH_MSGECHOICE );
00360     ASSERT( coarseIn->psi3Max > coarseIn->psi3Min, status,
00361             LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE );
00362     ASSERT( coarseIn->betaMax > coarseIn->betaMin, status,
00363             LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE );
00364     havePsi = 1;
00365   }
00366   /* Check that noise curve exists. */
00367   ASSERT( coarseIn->shf.data, status, LALINSPIRALBANKH_ENULL,
00368           LALINSPIRALBANKH_MSGENULL );
00369   ASSERT( coarseIn->shf.data->data, status, LALINSPIRALBANKH_ENULL,
00370           LALINSPIRALBANKH_MSGENULL );
00371 
00372   /* Allocate memory for 3x3 parameter-space metric & eigenvalues. */
00373   LALU4CreateVector( status->statusPtr, &metricDimensions, (UINT4) 2 );
00374   BEGINFAIL(status)
00375     cleanup(status->statusPtr, &metric, &metricDimensions, &eigenval, *tiles, tmplt, ntiles);
00376   ENDFAIL(status);
00377   metricDimensions->data[0] = 3;
00378   metricDimensions->data[1] = 3;
00379   LALSCreateArray( status->statusPtr, &metric, metricDimensions );
00380   BEGINFAIL(status)
00381     cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt, ntiles);
00382   ENDFAIL(status);
00383   eigenval = NULL;
00384   LALSCreateVector( status->statusPtr, &eigenval, 3 );
00385   BEGINFAIL(status)
00386     cleanup(status->statusPtr,&metric, &metricDimensions,&eigenval,*tiles,tmplt, ntiles);
00387   ENDFAIL(status);
00388 
00389   /* Set f0 to frequency of minimum of noise curve. */
00390   for( cnt = 0; cnt < (INT4) coarseIn->shf.data->length; cnt++ )
00391   {
00392     if( coarseIn->shf.data->data[cnt] > 0 && coarseIn->shf.data->data[cnt] <
00393         shf0 )
00394     {
00395       f0 = (REAL4) coarseIn->shf.deltaF * cnt;
00396       shf0 = coarseIn->shf.data->data[cnt];
00397     }
00398   }
00399   /* Compute noise moments. */
00400   inspiralTemplate.fLower = coarseIn->fLower;
00401   inspiralTemplate.fCutoff = coarseIn->fUpper;
00402   LALGetInspiralMoments( status->statusPtr, &moments, &(coarseIn->shf),
00403                          &inspiralTemplate );
00404   BEGINFAIL(status)                                                           
00405     cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
00406   ENDFAIL(status);
00407 
00408   /* Find the metric. */
00409   LALInspiralSpinBankMetric(status->statusPtr, metric, &moments, &inspiralTemplate, &f0);       
00410   BEGINFAIL(status)
00411     cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt, ntiles);
00412   ENDFAIL(status);
00413   /* Find eigenvalues and eigenvectors. */
00414   LALSSymmetricEigenVectors( status->statusPtr, eigenval, metric );
00415   BEGINFAIL(status)
00416     cleanup(status->statusPtr,&metric, &metricDimensions,&eigenval,*tiles,tmplt, ntiles);
00417   ENDFAIL(status);
00418 
00419   /* Allocate first template, which will remain blank. */
00420   *tiles = tmplt = (SnglInspiralTable *) LALCalloc( 1,
00421                    sizeof( SnglInspiralTable ) );
00422   if ( *tiles == NULL )
00423   {
00424     cleanup( status->statusPtr, &metric, &metricDimensions, &eigenval,
00425              *tiles, tmplt, ntiles);
00426     ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
00427   }
00428   *ntiles = 0;
00429 
00430   /* Set stepsizes from eigenvalues and angle from eigenvectors. */
00431   if( eigenval->data[0] <= 0 || eigenval->data[1] <=0 || eigenval->data[2]
00432       <= 0 )
00433   {
00434     ABORT(status, LALINSPIRALBANKH_ECHOICE, LALINSPIRALBANKH_MSGECHOICE);
00435   }
00436   dxp = 1.333333*sqrt(2*(1-coarseIn->mmCoarse)/eigenval->data[0]);
00437   dyp = 1.333333*sqrt(2*(1-coarseIn->mmCoarse)/eigenval->data[1]);
00438   dzp = 0.6666667*sqrt(2*(1-coarseIn->mmCoarse)/eigenval->data[2]);
00439   theta = atan2( -metric->data[3], -metric->data[0] );
00440 printf( "theta is %e\n", theta );
00441 
00442   /* If target region is given in terms of masses... */
00443   if ( ! havePsi )
00444   {
00445     /* Hardcode mass range on higher mass for the moment. */
00446     m2Min = coarseIn->mMin*LAL_MTSUN_SI;
00447     m2Max = coarseIn->MMax*LAL_MTSUN_SI/2;
00448     m1Min = 2.0*m2Max;
00449     m1Max = 15.0*LAL_MTSUN_SI - m2Max;
00450 
00451     /* Set box on unprimed phenom coordinates including region. */
00452     x0 = 0.9*(3.0/128) / (pow(LAL_PI*f0*(m1Max+m2Max),1.666667)
00453          *(m1Max*m2Max/pow(m1Max+m2Max,2)));
00454     myy0 = 1.1*(-.375*LAL_PI) / (pow(LAL_PI*f0*(m1Max+m2Min),0.6666667)*(m1Max*m2Min/pow(m1Max+m2Min,2)));
00455     z0 = 0;
00456     x1 = 1.1*(3.0/128) / (pow(LAL_PI*f0*(m1Min+m2Min),1.666667)*(m1Min*m2Min/pow(m1Min+m2Min,2)));
00457     myy1 = .9*(-.375*LAL_PI) / (pow(LAL_PI*f0*(m1Min+m2Max),0.6666667)*(m1Min*m2Max/pow(m1Min+m2Max,2)));
00458     z1 = 3.8* LAL_PI/29.961432 * (1+0.75*m2Max/m1Min) * (m1Max/m2Min) * pow(LAL_MTSUN_SI*100.0/(m1Min+m2Min), 0.6666667);
00459   }
00460   /* Target region is given in terms of psi etc (unprimed). */
00461   else
00462   {
00463     /* Rescale to dimensionless parameters used internally. */
00464     x0 = coarseIn->psi0Min / pow( f0, 5./3 );
00465     x1 = coarseIn->psi0Max / pow( f0, 5./3 );
00466     myy0 = coarseIn->psi3Min / pow( f0, 2./3 );
00467     myy1 = coarseIn->psi3Max / pow( f0, 2./3 );
00468     z0 = coarseIn->betaMin / pow( f0, 2./3 );
00469     z1 = coarseIn->betaMax / pow( f0, 2./3 );
00470   }
00471 
00472   /* Set boundaries of bigger box in primed (eigen) coordinates. */
00473   xp0 = x0 + sin(theta)*sin(theta) * (x1 - x0);
00474   yp0 = myy0 - cos(theta)*sin(theta) * (x1 - x0);
00475   yp1 = sin(theta) * (x1 - x0) + cos(theta) * (myy1 - myy0);
00476   xp1 = sin(theta) * (myy1 - myy0) + cos(theta) * (x1 - x0);
00477   zp0 = z0;
00478   zp1 = z1;
00479 
00480   /* This loop generates the template bank. */
00481   for (zp = 0; zp <= zp1; zp += dzp)
00482   {
00483     bccFlag++;
00484     for (yp = 0; yp<= yp1; yp += dyp)
00485     {
00486       for (xp = 0; xp <= xp1; xp += dxp)
00487       {
00488 
00489         /* If the point is in the target region, allocate a template. */
00490         x = calculateX(0, xp0, xp, dxp, yp, dyp, bccFlag, theta);
00491         y = calculateY(0, yp0, xp, dxp, yp, dyp, bccFlag, theta);
00492         z = calculateZ(0, zp, dzp);
00493         if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
00494             || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00495         {
00496           allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
00497           if( tmplt == NULL )
00498           {
00499             cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
00500             ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
00501           }
00502         }
00503         
00504         /* If dx behind is not in region, try dx/2 behind. */
00505         x = calculateX(-1, xp0, xp, dxp, yp, dyp, bccFlag, theta);
00506         if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
00507             || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00508         {
00509           x = calculateX(-0.5, xp0, xp, dxp, yp, dyp, bccFlag, theta);
00510           if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
00511               || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00512           {
00513             allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
00514             if( tmplt == NULL )
00515             {
00516               cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
00517               ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
00518             }
00519           }
00520         }
00521 
00522         /* If dy behind is not in region, try dy/2 behind. */
00523         x = calculateX(0, xp0, xp, dxp, yp, dyp, bccFlag, theta);
00524         y = calculateY(-1, yp0, xp, dxp, yp, dyp, bccFlag, theta);
00525         if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
00526             || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00527         {
00528           y = calculateY(-0.5, yp0, xp, dxp, yp, dyp, bccFlag, theta);
00529           if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
00530               || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00531           {
00532             allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
00533             if (!tmplt){
00534               cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
00535               ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
00536               }
00537           }
00538         }
00539 
00540         /* If dz behind is not in region, try dz/2 behind. */
00541         y = calculateY(0, yp0, xp, dxp, yp, dyp, (bccFlag+1), theta);
00542         z = calculateZ(-1, zp, dzp);
00543         if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
00544             || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00545         {
00546           z = calculateZ(-0.5, zp, dzp);
00547           if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
00548               || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00549           {
00550             allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
00551             if (!tmplt){
00552               cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
00553               ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
00554               }
00555           }
00556         }
00557 
00558         /* If dx ahead is not in region, try dx/2 ahead. */
00559         x = calculateX(1, xp0, xp, dxp, yp, dyp, bccFlag, theta);
00560         y = calculateY(0, yp0, xp, dxp, yp, dyp, (bccFlag+1), theta);
00561         z = calculateZ(0, zp, dzp);
00562         if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
00563             || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00564         {
00565           x = calculateX(0.5, xp0, xp, dxp, yp, dyp, bccFlag, theta);
00566           if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
00567               || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00568           {
00569             allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
00570             if (!tmplt){
00571               cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
00572               ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
00573               }
00574           }
00575         }
00576 
00577         /* If dy ahead is not in region, try dy/2 ahead. */
00578         x = calculateX(0, xp0, xp, dxp, yp, dyp, bccFlag, theta);
00579         y = calculateY(1, yp0, xp, dxp, yp, dyp, bccFlag, theta);
00580         if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
00581             || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00582         {
00583           y = calculateY(0.5, yp0, xp, dxp, yp, dyp, bccFlag, theta);
00584           if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
00585               || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00586           {
00587             allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
00588             if (!tmplt){
00589               cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
00590               ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
00591               }
00592           }
00593         }
00594 
00595         /* If dz ahead is not in region, try dz/2 ahead. */
00596         y = calculateY(0, yp0, xp, dxp, yp, dyp, (bccFlag+1), theta);
00597         z = calculateZ(1, zp, dzp);
00598         if( ( havePsi && ! inPsiRegion( x, y, z, coarseIn, f0 ) )
00599             || ( ! havePsi && ! test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00600         {
00601           z = calculateZ(0.5, zp, dzp);
00602           if( ( havePsi && inPsiRegion( x, y, z, coarseIn, f0 ) )
00603               || ( ! havePsi && test(x,y,z,m1Min,m1Max,m2Min,m2Max,f0) ) )
00604           {
00605             allocate( x, y, z, f0, &tmplt, ntiles, havePsi );
00606             if (!tmplt){
00607               cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
00608               ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
00609               }
00610           }
00611         }
00612       } /* for (zp...) */
00613     } /* for (yp...) */
00614   } /* for (zp...) */
00615 
00616   /* Trim the first template, which was left blank. */
00617   tmplt = (*tiles)->next;
00618   LALFree( *tiles );
00619   *tiles = tmplt;
00620 
00621   /* What if no templates were allocated? ABORT */
00622   if (*tiles == NULL) 
00623   {  
00624     cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,*tiles,tmplt,ntiles);
00625     ABORT(status, INSPIRALSPINBANKC_ENOTILES, INSPIRALSPINBANKC_MSGENOTILES);
00626   }
00627 
00628   /* free memory allocated for the vectors and arrays */
00629   cleanup(status->statusPtr,&metric,&metricDimensions,&eigenval,NULL,NULL,&cnt);
00630   DETATCHSTATUSPTR( status );
00631   RETURN( status );
00632 } /* LALInspiralSpinBank() */
00633 
00634 
00635 /* Try to free up memory. */
00636 static void cleanup(
00637     LALStatus *s, 
00638     REAL4Array **m, 
00639     UINT4Vector **md, 
00640     REAL4Vector **e, 
00641     SnglInspiralTable *f,
00642     SnglInspiralTable *t,
00643     INT4 *nt)
00644 {
00645   INITSTATUS( s, "LALInspiralSpinBank-cleanup", INSPIRALSPINBANKC );
00646   ATTATCHSTATUSPTR( s );
00647 
00648   if (m){
00649     TRY(LALU4DestroyVector(s->statusPtr,md),s);
00650     }
00651   if (md){
00652     TRY(LALSDestroyVector(s->statusPtr, e),s);
00653     }
00654   if (e){
00655     TRY(LALSDestroyArray(s->statusPtr, m),s); 
00656     }
00657   if (t && f)
00658   {
00659     t = f;
00660     while ((t->next) && (*nt > 0))
00661     {
00662       f = t;
00663       t = t->next;
00664       LALFree(f);
00665       --(*nt);
00666     }/* while(tmplt) */
00667   LALFree(t);
00668   --(*nt);
00669   }
00670   DETATCHSTATUSPTR( s );
00671   RETURN( s );
00672 }
00673 
00674 static REAL4 calculateX(REAL4 n,
00675                REAL4 xp0,
00676                REAL4 xp,
00677                REAL4 dxp,
00678                REAL4 yp,
00679                REAL4 dyp,
00680                INT4 bccFlag, 
00681                REAL4 theta)
00682   {
00683   return xp0 + (n*dxp + xp+dxp/2.0*(bccFlag%2))*cos(theta) - 
00684                 (yp+dyp/2.0*(bccFlag%2))*sin(theta);
00685   } /* REAL4 x(); */
00686 
00687 static REAL4 calculateY(REAL4 n,
00688                REAL4 yp0,
00689                REAL4 xp,
00690                REAL4 dxp,
00691                REAL4 yp,
00692                REAL4 dyp,
00693                INT4 bccFlag,
00694                REAL4 theta)
00695   {
00696   return (yp0 + (xp+dxp/2.0*((bccFlag)%2))*sin(theta) + 
00697                 (n*dyp + yp+dyp/2.0*((bccFlag)%2))*cos(theta));
00698   } /* REAL4 y(); */
00699 
00700 static REAL4 calculateZ(REAL4 n,
00701                REAL4 zp,
00702                REAL4 dzp)
00703   {
00704   return (zp + n*dzp);
00705   } /* REAL4 z(); */
00706 
00707 
00708 /* Check if we're in physical parameter region. */
00709 static INT4 test(REAL4 x, 
00710                  REAL4 y, 
00711                  REAL4 z,
00712                  REAL4 m1Min,
00713                  REAL4 m1Max,
00714                  REAL4 m2Min,
00715                  REAL4 m2Max,
00716                  REAL4 f0){
00717 
00718   REAL4 mass, eta, m1, m2, betaMax;
00719   mass = -y/x / (16.0*LAL_PI*LAL_PI*f0);
00720   if (mass < 0)
00721      return 0;
00722   eta = 16.0457 * pow( -x*x/y/y/y/y/y, 0.3333333 );
00723   if (eta > 0.25 || eta < 0)
00724     return 0;
00725   m1 = 0.5*mass* (1 + sqrt(1 - 4*eta));
00726   m2 = 0.5*mass* (1 - sqrt(1 - 4*eta));
00727   if (m1 > m1Max || m1 < m1Min || m2 > m2Max || m2 < m2Min)
00728     return 0;
00729   betaMax = 3.8*LAL_PI/29.961432 * (1+0.75*m2/m1)*(m1/m2) * pow((LAL_MTSUN_SI*100.0/mass),0.6666667);
00730   if (z > betaMax)
00731     return 0;
00732   return 1;
00733 }
00734 
00735 
00736 /* Check eigencoordinates to see if we're in the target region. Used only
00737  * if the parameter range is given as psi's rather than masses.
00738  */
00739 static BOOLEAN inPsiRegion( REAL4 psi0,
00740                             REAL4 psi3,
00741                             REAL4 beta,
00742                             InspiralCoarseBankIn *coarseIn,
00743                             REAL4 f0 )
00744 {
00745   REAL4 fac1 = pow( f0, 5./3 );
00746   REAL4 fac2 = fac1 / f0;
00747 
00748   if ( psi0 < coarseIn->psi0Min/fac1 )
00749     return 0;
00750   if ( psi0 > coarseIn->psi0Max/fac1 )
00751     return 0;
00752   if ( psi3 < coarseIn->psi3Min/fac2 )
00753     return 0;
00754   if ( psi3 > coarseIn->psi3Max/fac2 )
00755     return 0;
00756   if ( beta < coarseIn->betaMin/fac2 )
00757     return 0;
00758   if ( beta > coarseIn->betaMax/fac2 )
00759     return 0;
00760 
00761   return 1;
00762 } /* inPsiRegion */

Generated on Mon Oct 13 02:31:45 2008 for LAL by  doxygen 1.5.2