LALInspiralHexagonalBank.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Thomas Cokelaer
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="LALInspiralHexagonalBankCV">
00021 Author: Cokelaer Thomas
00022 $Id: LALInspiralHexagonalBank.c,v 1.6 2007/06/08 14:41:42 bema Exp $
00023 </lalVerbatim>  */
00024 
00025 /*  <lalLaTeX>
00026 
00027 \subsection{Module \texttt{LALInspiralHexagonalBank.c}}
00028 
00029 \subsubsection*{Prototypes}
00030 \vspace{0.1in}
00031 \input{LALInspiralHexagonalBankCP}
00032 \idx{LALInspiralHexagonalBank()}
00033 
00034 \subsubsection*{Description}
00035 
00036 \subsubsection*{Algorithm}
00037 
00038 \subsubsection*{Uses}
00039 \begin{verbatim}
00040 LALInspiralParameterCalc()
00041 LALInspiralComputeMetric()
00042 \end{verbatim}
00043 
00044 \subsubsection*{Notes}
00045 
00046 \vspace{0.1in}
00047 \vfill{\footnotesize\input{LALInspiralHexagonalBankCV}}
00048 </lalLaTeX>  */
00049 
00050 #include <stdio.h>
00051 #include <lal/LALInspiralBank.h>
00052 #include <lal/AVFactories.h>
00053 #include <lal/SeqFactories.h>
00054 #include <lal/LALStdio.h>
00055 #include <lal/FindRoot.h>
00056 
00057 
00058 /* Thomas:: definition for hexagonal grid. */
00059 
00060 
00061 NRCSID(LALINSPIRALHEXAGONALBANKC, "$Id: LALInspiralHexagonalBank.c,v 1.6 2007/06/08 14:41:42 bema Exp $");
00062 
00063 
00064 void 
00065 LALInspiralCreatePNCoarseBankHexa(
00066     LALStatus            *status, 
00067     InspiralTemplateList **list, 
00068     INT4                 *nlist,
00069     InspiralCoarseBankIn coarseIn
00070     ) 
00071 {  
00072   INT4                  i; 
00073   INT4                  firstId = 0;
00074   REAL4                 piFl;
00075   REAL4                 A0, A3; 
00076   InspiralBankParams    bankPars;
00077   InspiralTemplate      *tempPars;
00078   InspiralMomentsEtc    moments;
00079   InspiralCell          *cells;  
00080   HexaGridParam         gridParam;
00081   CellEvolution         cellEvolution;
00082   CellList              *cellList = NULL;
00083 
00084   INITSTATUS( status, "LALInspiralHexagonalBank", 
00085       LALINSPIRALHEXAGONALBANKC );
00086   ATTATCHSTATUSPTR( status );
00087 
00088   ASSERT( coarseIn.mMin > 0., status, 
00089       LALINSPIRALBANKH_ESIZE, LALINSPIRALBANKH_MSGESIZE );
00090   ASSERT( coarseIn.mMax > 0., status, 
00091       LALINSPIRALBANKH_ESIZE, LALINSPIRALBANKH_MSGESIZE );
00092   ASSERT( coarseIn.MMax >= 2.*coarseIn.mMin, status, 
00093       LALINSPIRALBANKH_ESIZE, LALINSPIRALBANKH_MSGESIZE );
00094 
00095   /* Set the elements of the metric and tempPars structures in  */
00096   /* conformity with the coarseIn structure                     */ 
00097   if ( !(tempPars = (InspiralTemplate *) 
00098                         LALCalloc( 1, sizeof(InspiralTemplate)))) 
00099   {
00100     LALFree(tempPars);
00101     LALFree(cells);
00102     ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
00103   }
00104 
00105   
00106   LALInspiralSetParams( status->statusPtr, tempPars, coarseIn );
00107   CHECKSTATUSPTR( status );
00108   
00109   /* Identify the boundary of search and parameters for the     */
00110   /* first lattice point                                        */
00111   LALInspiralSetSearchLimits( status->statusPtr, &bankPars, coarseIn );
00112   CHECKSTATUSPTR( status );
00113   
00114   tempPars->totalMass   = coarseIn.MMax;
00115   tempPars->eta         = 0.25;
00116   tempPars->ieta        = 1.L;
00117   tempPars->fLower      = coarseIn.fLower;
00118   tempPars->massChoice  = m1Andm2;
00119   tempPars->mass1       = coarseIn.mMin;
00120   tempPars->mass2       = coarseIn.mMax;
00121   
00122   LALInspiralParameterCalc( status->statusPtr, tempPars );
00123   CHECKSTATUSPTR( status );
00124   
00125   /* Get the moments of the PSD integrand and other parameters */
00126   /* required in the computation of the metric  once for all.   */
00127   LALGetInspiralMoments( 
00128                 status->statusPtr, 
00129                 &moments,
00130                 &coarseIn.shf,
00131                 tempPars );
00132   CHECKSTATUSPTR( status );
00133   
00134   /* Allocate memory for one cell */
00135   cells = (InspiralCell*)
00136       LALCalloc(1,   sizeof(InspiralCell) );
00137 
00138   /*define gridParam*/
00139   gridParam.mm                  = coarseIn.mmCoarse;
00140   gridParam.x0Min       = bankPars.x0Min;
00141   gridParam.x0Max       = bankPars.x0Max;
00142   gridParam.x1Min       = bankPars.x1Min;
00143   gridParam.x1Max       = bankPars.x1Max;
00144   gridParam.mMin        = coarseIn.mMin;
00145   gridParam.mMax        = coarseIn.mMax;
00146   gridParam.MMin        = coarseIn.MMin;
00147   gridParam.MMax        = coarseIn.MMax;
00148   gridParam.etaMin      = coarseIn.etamin;
00149   gridParam.space       = coarseIn.space;
00150   gridParam.massRange   = coarseIn.massRange;
00151   gridParam.gridSpacing = coarseIn.gridSpacing;
00152   
00153 
00154   cellEvolution.nTemplate               = 1;
00155   cellEvolution.nTemplateMax    = 1;
00156   cellEvolution.fertile                 = 0;
00157 
00158   /* initialise that first cell */
00159   tempPars->massChoice  = t03;
00160   cells[0].t0           = tempPars->t0;
00161   cells[0].t3           = tempPars->t3;
00162 
00163   /* some aliases */
00164   piFl  = LAL_PI * tempPars->fLower;
00165   A0    = 5. / pow(piFl, 8./3.) / 256.;
00166   A3    = LAL_PI / pow(piFl, 5./3.)/8.;
00167 
00168 
00169   /* Initialise the first template */
00170   LALInitHexagonalBank(
00171                         status->statusPtr, 
00172                         &cells, firstId, 
00173                         &moments, tempPars,
00174                         &gridParam, &cellEvolution, 
00175                         &cellList);
00176   CHECKSTATUSPTR( status );
00177 
00178   {
00179     INT4 k, kk; /*some indexes*/
00180     INT4 *list          = NULL;
00181     CellList *ptr       = NULL;
00182     INT4 length         = 1; /* default size of the bank when we 
00183                                                 start the bank generation. */
00184 
00185     /* we re-allocate an array which size equals the 
00186      * template bank size. */
00187     if (! (list =  LALMalloc(length*sizeof(INT4))))
00188     {
00189       ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
00190     }
00191 
00192     /* while there are cells/template which can propagate, we carry on the loop.*/
00193     while (cellEvolution.fertile) 
00194     {
00195       length = LALListLength(cellList);
00196       /*realloc some memory for the next template*/
00197       if (! (list =  LALRealloc(list, length*sizeof(INT4))))
00198       {
00199                 ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
00200                 /* freeing memory here ? */
00201       }
00202       ptr = cellList;
00203       /* we extract the ids which might change within the LALPopulateCell 
00204        * function. Indeed the bank might grow and then we will lost track 
00205        * of ids/bank size and so on. */
00206       for ( k = 0; k < length; k++)
00207       {
00208                 list[k] = ptr->id;      
00209                 ptr = ptr->next;
00210       }
00211       /* look at all the template/ids in the current bank to search for fertile cells */
00212       for (kk = 0; kk < length; kk++)
00213           {     
00214                 k = list[kk];
00215                 if ( cells[k].status == Fertile) 
00216                 {
00217           LALPopulateCell(status->statusPtr, &moments, &cells,
00218               k,  tempPars, &gridParam, &cellEvolution, &cellList);          
00219                   CHECKSTATUSPTR( status );                       
00220                   /* now the bank might have grown, but we only look at the 
00221                    * template created before this for loop, when we entered 
00222                    * in the while loop
00223                    * */
00224         }
00225       }
00226     }
00227     LALFree(list);
00228   }
00229   
00230   if (cellList != NULL)
00231     ABORT(status, LALINSPIRALBANKH_EHEXAINIT,LALINSPIRALBANKH_MSGEHEXAINIT);
00232         /* Here is the current number of template generated. Now, we need 
00233          * to clean some of them which might be redundant.
00234          * */
00235   *nlist = cellEvolution.nTemplate;
00236 
00237   {
00238     INT4 k ;
00239     INT4 length;
00240     length = cellEvolution.nTemplate;
00241 
00242     for ( k = 0; k < length; k++)
00243     {  
00244       REAL4 a;
00245       REAL4 b;
00246       REAL4 x0;
00247       REAL4 tempA3;
00248       SFindRootIn input;
00249       INT4 valid;
00250 
00251       PRIN  prin;
00252         
00253       tempA3              = pow(A3, -5./2.)/pow(0.25,-1.5);
00254       tempPars->t0        = cells[k].t0;
00255       tempPars->t3        = cells[k].t3;
00256 
00257       /* if non physical parameter i.e below eta=0.25*/
00258       if(cells[k].RectPosition[0] == Below ) 
00259       {   
00260         INT4 above=0, below=0, in=0, out=0;
00261                   
00262                 /*first, we define the line which is along the long semi-axis of the 
00263                  * ambiguity function, defined by the angle theta and the position of 
00264                  * the template.
00265                  * */                     
00266                 a = tan(cells[k].metric.theta);
00267                 b = cells[k].t3 - a * cells[k].t0;
00268                 /* and call a function to search for a solution along eta=1/4 */
00269                 input.function  = LALSPAF;
00270                 input.xmin              = cells[k].t3-1e-3;
00271                 input.xmax              = 1000;
00272                 input.xacc              = 1e-6;
00273         
00274                 prin.ct = a * A0 * tempA3;
00275                 prin.b = b;
00276         
00277                 LALSBisectionFindRoot(status->statusPtr,
00278                         &x0, &input, (void *)&prin);
00279                 CHECKSTATUSPTR( status );         
00280         
00281                 tempPars->t3 = x0 + 1e-3; /* to be sure it is physical */
00282                 tempPars->t0 = (tempPars->t3 - b)/a;
00283                 if (tempPars->t0 > 0) 
00284                 {
00285                   LALInspiralParameterCalc(status->statusPtr, tempPars);
00286                   CHECKSTATUSPTR( status );                       
00287         }
00288                 cells[k].t0  = tempPars->t0;
00289                 cells[k].t3  = tempPars->t3;    
00290                 
00291                 /* update its position values */
00292                 valid = 1;
00293                 GetPositionRectangle(status->statusPtr, &cells, k,  tempPars , 
00294                              &gridParam, 
00295                              &cellEvolution, 
00296                              &cellList, 
00297                              &valid);
00298         
00299                 {
00300                         switch (cells[k].RectPosition[1]){
00301                           case In:    in    +=1; break;
00302                           case Below: below +=1; break;
00303                           case Above: above +=1; break;
00304                           case Out:   out   +=1; break;
00305                           }
00306                           switch (cells[k].RectPosition[2]){
00307                           case In:    in    +=1; break;
00308                           case Below: below +=1; break;
00309                           case Above: above +=1; break;
00310                           case Out:   out   +=1; break;
00311                           }
00312                           switch (cells[k].RectPosition[3]){
00313                           case In:    in    +=1; break;
00314                           case Below: below +=1; break;
00315                           case Above: above +=1; break;
00316                           case Out:   out   +=1; break;
00317                           }
00318                           switch (cells[k].RectPosition[4]){
00319                           case In:    in    +=1; break;
00320                           case Below: below +=1; break;
00321                           case Above: above +=1; break;
00322                           case Out:   out   +=1; break;
00323                           }
00324                         }
00325 
00326                   if (above == 2 && cells[k].position == In)
00327                   {
00328                     cells[cells[k].child[0]].position = Out;        
00329                   }
00330       }  
00331     }
00332   }
00333 
00334   for (i=0; i<cellEvolution.nTemplate; i++) {
00335     if (cells[i].position == In ) {
00336       *nlist = *nlist +1; 
00337     }
00338   }
00339 ;
00340 
00341 
00342   /* allocate appropriate memory and fill the output bank */
00343   *list = (InspiralTemplateList*) 
00344     LALRealloc( *list, sizeof(InspiralTemplateList) * (*nlist+1) );
00345   if ( ! *list )
00346   {
00347     LALFree( tempPars );
00348     ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
00349   }
00350   memset( *list + *nlist, 0, sizeof(InspiralTemplateList) );
00351   {
00352     *nlist = 0 ;
00353     for (i=0; i<cellEvolution.nTemplate; i++) 
00354     {
00355       if (cells[i].position == In) 
00356       {
00357         tempPars->t0  = cells[i].t0;
00358         tempPars->t3  = cells[i].t3;
00359         tempPars->massChoice = t03;
00360         tempPars->fLower = coarseIn.fLower;
00361 
00362         LALInspiralParameterCalc( status->statusPtr, tempPars );
00363         CHECKSTATUSPTR( status );
00364             
00365         (*list)[*nlist].ID            = *nlist; 
00366         (*list)[*nlist].params        = *tempPars; 
00367         (*list)[*nlist].metric        = cells[i].metric; 
00368         ++(*nlist); 
00369       }
00370     }
00371   }
00372    
00373   LALFree( cells );
00374   LALFree( tempPars );
00375     
00376   DETATCHSTATUSPTR( status );
00377   RETURN ( status );
00378 }
00379   
00380 
00381 
00382 
00383 
00384 void
00385 LALPopulateCell(
00386                 LALStatus               *status,
00387                 InspiralMomentsEtc      *moments,
00388                 InspiralCell            **cell, 
00389                 INT4                     headId,
00390                 InspiralTemplate        *paramsIn,
00391                 HexaGridParam           *gridParam,
00392                 CellEvolution           *cellEvolution, 
00393                 CellList                **cellList
00394                 )
00395 {
00396   REAL4 dx0, dx1;
00397   REAL4 newt0, newt3;  
00398   INT4 i, id1, id2;
00399   REAL4 theta, ctheta, stheta;
00400   INT4 offSpring;
00401   INT4 it;
00402   INT4 add = 0;
00403 
00404   INITSTATUS( status, "LALPopulateCell", 
00405               LALINSPIRALHEXAGONALBANKC );
00406   ATTATCHSTATUSPTR( status );
00407 
00408   /* aliases to get the characteristics of the parent template, 
00409    * that we refer to its ID (headId) */  
00410   dx0           = (*cell)[headId].dx0;
00411   dx1           = (*cell)[headId].dx1;
00412   theta         = (*cell)[headId].metric.theta;
00413   ctheta        = cos(theta);
00414   stheta        = sin(theta);
00415   offSpring     = cellEvolution->nTemplate;
00416 
00417    /* Around the parent, the offspring can be at most 6 (hexagonal grid). 
00418    * By default the child are unset. If so it is created and have the 
00419    * properties of its parents. However, a child migh have been created 
00420    * earlier. In that case, we do not do anything.  */  
00421   it = 0 ; 
00422 
00423   for (i = 0; i < 6; i++) 
00424   {
00425     if ((*cell)[headId].child[i] == -1) 
00426     {
00427       add++;
00428       /* reallocate memory by set of 1000 cells if needed*/
00429       if ( (offSpring+add)>cellEvolution->nTemplateMax)
00430       {
00431         *cell = (InspiralCell*) 
00432           LALRealloc( *cell,
00433            sizeof(InspiralCell) * (cellEvolution->nTemplateMax + 1000) );
00434         if ( !cell ) {
00435           ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
00436         }
00437         cellEvolution->nTemplateMax +=  1000;
00438       }
00439       
00440       /* creates the child connection if needed. A child heritates the
00441        * properties of its parent */
00442       switch ( i ){
00443       case 0:
00444                 newt0   = dx0 ;
00445                 newt3   = 0 ;
00446                 (*cell)[offSpring + it].t0   = (*cell)[headId].t0;
00447                 (*cell)[offSpring + it].t3   = (*cell)[headId].t3;
00448                 (*cell)[offSpring + it].t0   += newt0 *ctheta + stheta* newt3;
00449                 (*cell)[offSpring + it].t3   += newt0 *stheta - ctheta* newt3;
00450                 LALInitHexagonalBank(status->statusPtr,  cell,  offSpring+it, 
00451                     moments, paramsIn, gridParam, cellEvolution, cellList);
00452                 break;
00453       case 1:
00454                 newt0   =   dx0/2. ;
00455                 newt3   =   -dx1 *sqrt(3./2) ;
00456                 (*cell)[offSpring + it].t0   = (*cell)[headId].t0;
00457                 (*cell)[offSpring + it].t3   = (*cell)[headId].t3;
00458                 (*cell)[offSpring + it].t0   += newt0 * ctheta + stheta * newt3;
00459                 (*cell)[offSpring + it].t3   += newt0 * stheta - ctheta * newt3;
00460                 LALInitHexagonalBank(status->statusPtr,  cell,  offSpring+it, 
00461                     moments, paramsIn, gridParam, cellEvolution, cellList);
00462                 break;
00463       case 2:
00464                 newt0   =  -dx0/2 ;
00465                 newt3   =  -dx1 *sqrt(3./2);
00466                 (*cell)[offSpring + it].t0   = (*cell)[headId].t0;
00467                 (*cell)[offSpring + it].t3   = (*cell)[headId].t3;
00468                 (*cell)[offSpring + it].t0   += newt0 * ctheta + stheta * newt3;
00469                 (*cell)[offSpring + it].t3   += newt0 * stheta - ctheta * newt3;
00470                 LALInitHexagonalBank(status->statusPtr,  cell,  offSpring+it, 
00471                     moments, paramsIn, gridParam, cellEvolution, cellList);
00472                 break;
00473       case 3:
00474                 newt0   = -dx0 ;
00475                 newt3   = 0;
00476                 (*cell)[offSpring + it].t0   = (*cell)[headId].t0;
00477                 (*cell)[offSpring + it].t3   = (*cell)[headId].t3;
00478                 (*cell)[offSpring + it].t0   += newt0 * ctheta + stheta * newt3;
00479                 (*cell)[offSpring + it].t3   += newt0 * stheta - ctheta * newt3;
00480                 LALInitHexagonalBank(status->statusPtr,  cell,  offSpring+it, 
00481                     moments, paramsIn, gridParam, cellEvolution, cellList);
00482                 break;
00483       case 4:
00484                 newt0   =  -dx0/2. ;
00485                 newt3   =  dx1 *sqrt(3./2);
00486                 (*cell)[offSpring + it].t0   = (*cell)[headId].t0;
00487                 (*cell)[offSpring + it].t3   = (*cell)[headId].t3;
00488                 (*cell)[offSpring + it].t0   += newt0 * ctheta + stheta * newt3;
00489                 (*cell)[offSpring + it].t3   += newt0 * stheta - ctheta * newt3;
00490                 LALInitHexagonalBank(status->statusPtr,  cell,  offSpring+it, 
00491                     moments, paramsIn, gridParam, cellEvolution, cellList);
00492                 break;
00493       case 5:
00494                 newt0   = dx0/2. ;
00495                 newt3   = dx1 *sqrt(3./2);
00496                 (*cell)[offSpring + it].t0   = (*cell)[headId].t0;
00497                 (*cell)[offSpring + it].t3   = (*cell)[headId].t3;
00498                 (*cell)[offSpring + it].t0   += newt0 * ctheta + stheta * newt3;
00499                 (*cell)[offSpring + it].t3   += newt0 * stheta - ctheta * newt3;
00500                 LALInitHexagonalBank(status->statusPtr,  cell,  offSpring+it, 
00501                     moments, paramsIn, gridParam, cellEvolution, cellList);
00502                 break;
00503       }      
00504       
00505       /* Now, tricky part, if a child has been creating, he must have a
00506        * connection with its parents and vice-versa.  */
00507       if ((*cell)[offSpring + it].child[(i+3)%6] == -1)
00508       {
00509                 (*cell)[offSpring + it].child[(i+3)%6] = (*cell)[headId].ID;
00510                 (*cell)[headId].child[i] = offSpring+it;
00511       }
00512       /* a new cell index */
00513       it += 1;
00514     }
00515   }
00516   
00517   cellEvolution->nTemplate +=it;
00518  
00519 
00520   /* Here, the parent has its 6 children set; he become sterile. */
00521   (*cell)[headId].status        = Sterile;
00522   (cellEvolution->fertile)      = cellEvolution->fertile-1;
00523   LALListDelete(cellList, headId);
00524 
00525   /* what shall we do with that parent. Is he valid ? inside the space,
00526    * outside since eta > 0.25 but close to the boundary .... */         
00527   {
00528     if ((*cell)[headId].RectPosition[0] == Above && (*cell)[headId].in == 1)
00529     {
00530           (*cell)[headId].RectPosition[0]=Out;
00531     }
00532   }
00533   
00534   /* propagate  connections to the brothers to avoid redundancies */  
00535   for (i=0; i<6; i++)
00536   {
00537         /* for each child*/
00538     id1 = (*cell)[headId].child[i%6];
00539     id2 = (*cell)[headId].child[(i+1)%6];
00540     (*cell)[id1].child[(i+2)%6] = (*cell)[id2].ID;
00541     (*cell)[id2].child[(i+4+1)%6] = (*cell)[id1].ID;   
00542   }
00543   
00544   /* enfin trouver position[0] (In/out)? of the children. */
00545   for (i=0; i<6; i++)
00546   {/* for each child find position[0]*/
00547     id1 = (*cell)[headId].child[i%6];
00548 
00549     if ((*cell)[id1].status == Fertile) 
00550     {
00551       LALSPAValidPosition(status->statusPtr, cell, id1, 
00552                           moments, cellEvolution, cellList);
00553       CHECKSTATUSPTR( status );
00554           
00555       if ((*cell)[id1].position != In ) 
00556       {
00557         if ((*cell)[id1].status == Fertile) 
00558         {
00559           (*cell)[id1].status= Sterile;
00560           cellEvolution->fertile=cellEvolution->fertile-1;
00561                   LALListDelete(cellList, id1);
00562         }
00563       }
00564     }
00565   }
00566     
00567   DETATCHSTATUSPTR( status );
00568   RETURN ( status );
00569 }
00570 
00571 
00572 
00573 void 
00574 LALInitHexagonalBank(
00575         LALStatus               *status,
00576         InspiralCell            **cell, 
00577         INT4                    id,
00578         InspiralMomentsEtc      *moments, 
00579         InspiralTemplate        *paramsIn, 
00580         HexaGridParam           *gridParam, 
00581         CellEvolution           *cellEvolution,
00582         CellList **cellList)
00583 {
00584   INT4          i;
00585   INT4          valid;   
00586   
00587   INITSTATUS( status, "LALInitHexagonalBank", 
00588               LALINSPIRALHEXAGONALBANKC );
00589   ATTATCHSTATUSPTR( status );
00590   
00591   /* a new cell is created; by default it can create new children, 
00592      therefore it is fertile */
00593   cellEvolution->fertile = cellEvolution->fertile + 1;;
00594   (*cell)[id].status = Fertile;  
00595   LALListAppend(cellList, id);
00596 
00597 
00598   /* all of whom are unset and do not have any id set yet*/
00599   for (i = 0; i < 6; i++) 
00600   {
00601     (*cell)[id].child[i] = -1;
00602   } 
00603  
00604   /* filled some values related to the space */
00605   (*cell)[id].ID        = id;  
00606   (*cell)[id].position  = In;
00607   (*cell)[id].metric.space = gridParam->space;
00608 
00609 
00610   /* before any further computation, check that t0, t3 are positive.*/
00611   if ((*cell)[id].t0 > 0 && (*cell)[id].t3 > 0)
00612   {
00613     /* Get the metric at the position of the cell */ 
00614     paramsIn->t0 = (*cell)[id].t0;
00615     paramsIn->t3 = (*cell)[id].t3;
00616 
00617     LALInspiralComputeMetric( status->statusPtr, 
00618                               &((*cell)[id].metric),
00619                               paramsIn,
00620                               moments);
00621     CHECKSTATUSPTR( status );
00622   
00623     /* let us store the dx0 and dx3 at that point. */
00624     (*cell)[id].dx0 = sqrt(2.L * (1.L - gridParam->mm)/(*cell)[id].metric.g00 );
00625     (*cell)[id].dx1 = sqrt(2.L * (1.L - gridParam->mm)/(*cell)[id].metric.g11 );
00626 
00627     LALFindPosition(status->statusPtr, (*cell)[id].dx0, (*cell)[id].dx1,
00628                     &((*cell)[id].RectPosition[0]), paramsIn, gridParam);
00629     CHECKSTATUSPTR( status );
00630 
00631     /* if outside, this is a sterile cell which can not propagate */  
00632     if ((*cell)[id].RectPosition[0] == Out) 
00633     {
00634       (*cell)[id].position      = Out;
00635       for (i = 0; i < 5; i++)
00636       {
00637         (*cell)[id].RectPosition[i] = Out;
00638       }
00639       (*cell)[id].status = Sterile;
00640       (cellEvolution->fertile)=cellEvolution->fertile-1;
00641       LALListDelete(cellList, id);      
00642       
00643       DETATCHSTATUSPTR(status);
00644       RETURN(status);
00645     }
00646     else
00647     {
00648       valid = 1;
00649       GetPositionRectangle(status->statusPtr, &(*cell), id,  paramsIn , 
00650                            gridParam, cellEvolution, &(*cellList), &valid);
00651     }
00652   }
00653   else
00654   {/* if t0 or t3 < 0 , this is not a valid cell*/
00655     valid = 0;   
00656   }
00657 
00658   /* If this is not a valid template, we remove it from the bank*/
00659   if (valid == 0)
00660   {
00661     for (i=0; i<5; i++)
00662     {
00663       (*cell)[id].RectPosition[i] = Out;
00664     }
00665     (*cell)[id].position                = Out;
00666     (*cell)[id].status                  = Sterile;
00667     (cellEvolution->fertile)    =cellEvolution->fertile-1;
00668     LALListDelete(cellList, id);
00669   }
00670 
00671 
00672 
00673 
00674 #if 1
00675   if (gridParam->gridSpacing == HybridHexagonal)
00676   {
00677     INT4 below=0, above=0;    
00678     for (i=1; i<=4; i++){
00679       if ( (*cell)[id].RectPosition[i] == Below) below++;
00680       if ( (*cell)[id].RectPosition[i] == Above) above++;
00681     }    
00682     if (below==2 && above == 2){
00683       (*cell)[id].status = Edge;
00684       (cellEvolution->fertile)=cellEvolution->fertile-1;
00685       LALListDelete(cellList, id);
00686       
00687     } 
00688   
00689 
00690   }
00691 #endif  
00692 
00693 
00694 
00695   DETATCHSTATUSPTR(status);
00696   RETURN(status);
00697 }
00698 
00699 
00700 
00701 /* Get the position of the rectangle corners which are inscribe within the ambiguity 
00702  * function. Are they within the parameter space or not ?*/
00703 void
00704 GetPositionRectangle(
00705                 LALStatus               *status, 
00706                 InspiralCell            **cell,
00707                 INT4                    id,
00708                 InspiralTemplate        *params, 
00709                     HexaGridParam               *gridParam, 
00710                     CellEvolution               *cellEvolution, 
00711                     CellList                    **cellList, 
00712                     INT4                                *valid)
00713 {
00714   RectangleIn   RectIn;
00715   RectangleOut  RectOut;
00716   InspiralTemplate paramsIn;
00717 
00718   INITSTATUS( status, "GetPosition", 
00719               LALINSPIRALHEXAGONALBANKC );
00720   ATTATCHSTATUSPTR( status );
00721 
00722   /* let us investigate this particular template : */
00723   RectIn.x0    = params->t0;
00724   RectIn.y0    = params->t3;
00725   RectIn.dx    = (*cell)[id].dx0 ;
00726   RectIn.dy    = (*cell)[id].dx1 ;
00727   RectIn.theta = (*cell)[id].metric.theta;
00728   
00729   /* what is the rectangle ? */
00730   LALRectangleVertices(status->statusPtr, &RectOut, &RectIn);
00731   CHECKSTATUSPTR( status );
00732 
00733   /* for each corner, let us decide where it lies in the parameter space */
00734   paramsIn = *params;
00735   paramsIn.t0 = RectOut.x1;
00736   paramsIn.t3 = RectOut.y1;
00737   
00738   if (RectOut.x1<0 || RectOut.y1<0
00739    || RectOut.x2<0 || RectOut.y2<0
00740    || RectOut.x3<0 || RectOut.y3<0
00741    || RectOut.x4<0 || RectOut.y4<0)
00742   {
00743         *valid = 0; 
00744     DETATCHSTATUSPTR(status);
00745     RETURN(status);     
00746   }
00747    
00748   if (RectOut.x1>0 && RectOut.y1>0)
00749   {
00750     LALFindPosition(status->statusPtr,(*cell)[id].dx0, (*cell)[id].dx1, 
00751                     &((*cell)[id].RectPosition[1]), 
00752                     &paramsIn, 
00753                     gridParam);    
00754     CHECKSTATUSPTR( status );
00755   }
00756   
00757   paramsIn.t0 = RectOut.x2;
00758   paramsIn.t3 = RectOut.y2;
00759   if (RectOut.x2>0 && RectOut.y2>0){
00760     LALFindPosition(status->statusPtr, (*cell)[id].dx0, (*cell)[id].dx1,
00761                     &((*cell)[id].RectPosition[2]), &paramsIn, gridParam);
00762     CHECKSTATUSPTR( status );
00763     
00764   }
00765   
00766   paramsIn.t0 = RectOut.x3;
00767   paramsIn.t3 = RectOut.y3; 
00768   if (RectOut.x3>0 && RectOut.y3>0)
00769   {
00770     LALFindPosition(status->statusPtr, (*cell)[id].dx0, (*cell)[id].dx1,
00771                     &((*cell)[id].RectPosition[3]), &paramsIn, gridParam);
00772     CHECKSTATUSPTR( status );
00773   }
00774   
00775   paramsIn.t0 = RectOut.x4;
00776   paramsIn.t3 = RectOut.y4;
00777   if (RectOut.x4>0 && RectOut.y4>0)
00778   {
00779     LALFindPosition(status->statusPtr, (*cell)[id].dx0, (*cell)[id].dx1,
00780                     &((*cell)[id].RectPosition[4]), &paramsIn, gridParam); 
00781     CHECKSTATUSPTR( status );
00782   }
00783     
00784   DETATCHSTATUSPTR( status );
00785   RETURN ( status );
00786 }
00787 
00788 
00789 
00790 
00791 
00792 
00793 
00794 
00795 void
00796 LALSPAValidPosition(LALStatus *status, 
00797                     InspiralCell **cell,
00798                     INT4 id1,
00799                     InspiralMomentsEtc *moments, 
00800                     CellEvolution *cellEvolution, 
00801                     CellList **cellList
00802                     )
00803 {
00804   INT4 below = 0, in = 0, out = 0, above = 0;
00805   
00806   INITSTATUS( status, "LALSPAFindPosition", 
00807               LALINSPIRALHEXAGONALBANKC );
00808   ATTATCHSTATUSPTR( status );
00809 
00810 
00811   switch ((*cell)[id1].RectPosition[1]){
00812   case In:    in    +=1; break;
00813   case Below: below +=1; break;
00814   case Above: above +=1; break;
00815   case Out:   out   +=1; break;
00816   }
00817   switch ((*cell)[id1].RectPosition[2]){
00818   case In:    in    +=1; break;
00819   case Below: below +=1; break;
00820   case Above: above +=1; break;
00821   case Out:   out   +=1; break;
00822   }
00823   switch ((*cell)[id1].RectPosition[3]){
00824   case In:    in    +=1; break;
00825   case Below: below +=1; break;
00826   case Above: above +=1; break;
00827   case Out:   out   +=1; break;
00828   }
00829   switch ((*cell)[id1].RectPosition[4]){
00830   case In:    in    +=1; break;
00831   case Below: below +=1; break;
00832   case Above: above +=1; break;
00833   case Out:   out   +=1; break;
00834   }
00835   switch ((*cell)[id1].RectPosition[0]){
00836   case In:    in    +=1; break;
00837   case Below: below +=1; break;
00838   case Above: above +=1; break;
00839   case Out:   out   +=1; break;
00840   }
00841 
00842   (*cell)[id1].in = in;
00843   
00844   if ((*cell)[id1].RectPosition[0]==In)
00845     {
00846       (*cell)[id1].position = In;
00847       if ((*cell)[id1].status == Sterile)
00848         {
00849           (*cell)[id1].status = Fertile;
00850           (cellEvolution->fertile)=cellEvolution->fertile+1;; 
00851           LALListAppend(cellList, id1);
00852         }
00853       DETATCHSTATUSPTR(status);
00854       RETURN(status);
00855   }
00856 
00857   if ( above == 5){
00858     (*cell)[id1].position = Out;
00859     if ((*cell)[id1].status == Fertile)
00860       {
00861         (*cell)[id1].status = Sterile;
00862         (cellEvolution->fertile)=cellEvolution->fertile-1;
00863         LALListDelete(cellList, id1);
00864 
00865       }
00866   }
00867   else if ( below == 5){
00868     (*cell)[id1].position = Out;
00869     if ((*cell)[id1].status == Fertile)
00870       {
00871         (*cell)[id1].status = Sterile;
00872         (cellEvolution->fertile)=cellEvolution->fertile-1;
00873         LALListDelete(cellList, id1);
00874 
00875       }
00876   }  
00877   else if ( out == 5){
00878     (*cell)[id1].position = Out;
00879     if ((*cell)[id1].status == Fertile)
00880       {
00881         (*cell)[id1].status = Sterile;
00882         (cellEvolution->fertile)=cellEvolution->fertile-1;
00883         LALListDelete(cellList, id1);
00884 
00885       }
00886   }
00887   else if (in >= 1){
00888     (*cell)[id1].position = In;
00889     if ((*cell)[id1].status == Sterile)
00890       {
00891         (*cell)[id1].status = Fertile;
00892         (cellEvolution->fertile)=cellEvolution->fertile+1;
00893         LALListAppend(cellList, id1);
00894       }
00895 
00896   }
00897   else if (above+below >= 5){
00898     if(out==1){
00899     (*cell)[id1].position = Out;
00900     if ((*cell)[id1].status == Fertile)
00901       {
00902         (*cell)[id1].status = Sterile;
00903         (cellEvolution->fertile)=cellEvolution->fertile-1;
00904         LALListDelete(cellList, id1);
00905 
00906       }
00907     }
00908     else
00909     {
00910     (*cell)[id1].position = In;
00911     if ((*cell)[id1].status == Sterile)
00912       {
00913         (*cell)[id1].status = Fertile;
00914         (cellEvolution->fertile)=cellEvolution->fertile-1;
00915         LALListDelete(cellList, id1);
00916 
00917 
00918       }
00919     }  
00920   }
00921   else{
00922     (*cell)[id1].position = Out;
00923     if ((*cell)[id1].status == Fertile)
00924       {
00925         (*cell)[id1].status = Sterile;
00926         (cellEvolution->fertile)=cellEvolution->fertile-1;
00927         LALListDelete(cellList, id1);
00928 
00929       }
00930   }
00931            
00932   DETATCHSTATUSPTR(status);
00933   RETURN(status);
00934 }
00935 
00936 
00937 void
00938 LALFindPosition(LALStatus       *status, 
00939                 REAL4                   dx0, 
00940                 REAL4                   dx1,
00941                 Position                *position, 
00942                 InspiralTemplate        *paramsIn,
00943                 HexaGridParam           *gridParam
00944 )
00945 {
00946   REAL8         mint3;  
00947   REAL4         eta;
00948   REAL4         totalMass,ieta, oneby4, tiny, piFl, A0, A3;
00949 
00950   INITSTATUS( status, "LALFindPosition", 
00951               LALINSPIRALHEXAGONALBANKC );
00952   ATTATCHSTATUSPTR( status );
00953 
00954   ieta          = 1.;
00955   oneby4        = 1./4.;
00956   tiny          = 1.e-10;
00957   piFl          = LAL_PI * paramsIn->fLower;
00958   A0    = 5. / pow(piFl, 8./3.) / 256.;
00959   A3    = LAL_PI / pow(piFl, 5./3.)/8.;
00960   
00961   ASSERT(paramsIn->t0 > 0., status, LALINSPIRALH_ESIZE, LALINSPIRALH_MSGESIZE);
00962