LALInspiralBCVSpinBank.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 B.S. Sathyaprakash, Thomas Cokelaer, Chris Van Den Broeck
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="LALInspiralBCVSpinBankCV">
00021 Authors: Tagoshi, H, Takahashi, H, Van Den Broeck, C, Jones, G, Sathyaprakash, BS
00022 $Id: LALInspiralBCVSpinBank.c,v 1.14 2007/06/08 14:41:42 bema Exp $
00023 </lalVerbatim>  */
00024 
00025 /*  <lalLaTeX>
00026 \subsection{Module \texttt{LALInspiralBCVSpinBank.c}}
00027 \subsubsection*{Prototypes}
00028 \subsubsection*{Description}
00029 \subsubsection*{Algorithm}
00030 \subsubsection*{Uses}
00031 \begin{verbatim}
00032 \end{verbatim}
00033 \subsubsection*{Notes}
00034 \clearpage
00035 </lalLaTeX>  */
00036 
00037 
00038 #include <math.h>
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042 
00043 #include <lal/AVFactories.h>
00044 #include <lal/FlatMesh.h>
00045 #include <lal/LALConfig.h>
00046 #include <lal/LALConstants.h>
00047 #include <lal/LALDatatypes.h>
00048 #include <lal/LALInspiralBank.h>
00049 #include <lal/LALMalloc.h>
00050 #include <lal/LALStatusMacros.h>
00051 #include <lal/LALStdlib.h>
00052 #include <lal/LIGOMetadataTables.h>
00053 #include <lal/SeqFactories.h>
00054 #include <lal/LALInspiralBCVSpinBank.h>
00055 #include <gsl/gsl_linalg.h>
00056 
00057 NRCSID(LALINSPIRALBCVSPINBANKC, "$Id: LALInspiralBCVSpinBank.c,v 1.14 2007/06/08 14:41:42 bema Exp $");
00058 
00059 /* <lalVerbatim file="LALInspiralBCVSpinBankCP"> */
00060 void
00061 LALInspiralBCVSpinBank(
00062     LALStatus            *status,
00063     SnglInspiralTable    **tiles,
00064     INT4                 *ntiles,
00065     InspiralCoarseBankIn *coarseIn
00066     )
00067 /* </lalVerbatim> */
00068 
00069 {
00070   /* Nmax is the maximum number of beta values we are allowed to have */
00071   INT4 Nmax=1000;
00072   INT4 N, k, nbeta, totTemps=0;
00073   REAL8 *Sn, MM, betaMin, betaMax;
00074   REAL8Vector newSn;
00075   REAL8 fmin, fmax, beta_list[Nmax+1];
00076   REAL8 effmetric_list[3][3][Nmax+1];
00077 
00078   /* Let us declare the metric, bank parameters and vector sequences that will
00079    * hold the psi0-psi3 values at the location of the templates 
00080    */
00081   static InspiralMetric metric;
00082   static InspiralBankParams bankParams;
00083   static CreateVectorSequenceIn in; 
00084   static REAL4VectorSequence *list=NULL;
00085   static REAL4VectorSequence *totList=NULL;
00086   SnglInspiralTable *bank=NULL, *tmpBank=NULL;
00087         
00088   INITSTATUS(status, "LALInspiralBCVSpinBank", LALINSPIRALBCVSPINBANKC );
00089   ATTATCHSTATUSPTR( status );
00090 
00091   ASSERT( coarseIn != NULL, status, LALINSPIRALBANKH_ENULL, LALINSPIRALBANKH_MSGENULL );
00092   ASSERT( *tiles == NULL, status, LALINSPIRALBANKH_ENULL, LALINSPIRALBANKH_MSGENULL );
00093         
00094   /*
00095    * Create the structure necessary for vector sequence to
00096    * temporarily store the values of psi0-psi3-beta.
00097    * list will store the values of psi0-psi3 at each beta level.
00098    * totList will store the values of psi0-psi3-beta which will
00099    * be used to fill the output structure tiles.
00100    */
00101   in.length = 1;
00102   in.vectorLength = 2;
00103           
00104   LALSCreateVectorSequence( status->statusPtr, &list, &in );
00105   CHECKSTATUSPTR( status );
00106 
00107   LALSCreateVectorSequence( status->statusPtr, &totList, &in );
00108   CHECKSTATUSPTR( status );
00109 
00110   /* 
00111    * coarseIn structure knows about the range of beta, psi0,
00112    * and psi3. It also provides the power spectrum of noise,
00113    * minimal match (in mmCoarse), upper and lower freq cutoffs.
00114    */
00115 
00116   MM = coarseIn->mmCoarse;
00117   fmin = coarseIn->fLower;
00118   fmax = coarseIn->fUpper;
00119   betaMin = coarseIn->betaMin;
00120   betaMax = coarseIn->betaMax;
00121   bankParams.minimalMatch = coarseIn->mmCoarse;
00122   bankParams.x0Min = coarseIn->psi0Min;
00123   bankParams.x0Max = coarseIn->psi0Max;
00124   bankParams.x1Min = coarseIn->psi3Min;
00125   bankParams.x1Max = coarseIn->psi3Max;
00126 
00127   /* We really don't know the metric; this is just to create a
00128    * place holder
00129    */
00130   bankParams.metric = &metric;
00131 
00132   /*
00133    * Instead of noisespec(N, Sn, fmin, fmax) let us use the noise
00134    * PSD provided by coarseIn.
00135    */
00136 
00137   Sn = coarseIn->shf.data->data;
00138   N = coarseIn->shf.data->length-1;
00139   newSn.length=0;
00140 
00141 #if 1
00142   if (N>32768)
00143   {
00144     int ratio, i;
00145     ratio = N/32768;
00146     N = N / ratio;
00147     LALInfo(status,  "entering BCVSpin metric computation using the smooth PSD \n");
00148     newSn.length= N;
00149 
00150     newSn.data  = (REAL8*) LALCalloc(1, sizeof(REAL8) * (newSn.length+1));
00151     for (i=0; i<N; i++)
00152     {
00153       int j;
00154       for (j=0;j<ratio; j++)
00155       {
00156         newSn.data[i]+=  coarseIn->shf.data->data[i*ratio+j];
00157       }
00158     newSn.data[i]/=ratio;
00159     }
00160     newSn.data[N] = coarseIn->shf.data->data[N*ratio];
00161     Sn = newSn.data; 
00162      
00163   }
00164 else
00165 {
00166     LALInfo(status,  "entering BCVSpin metric computation using the whole PSD\n");
00167 }
00168 #endif
00169 
00170 /*  printf("Num beta steps=%d Sn[0]=%e, Sn[N/2]=%e, MM=%f\n", N, Sn[0], Sn[N/2], MM);*/
00171 
00172   /* Use Tagoshi's code to get values of beta b/w betaMin and betaMax at
00173    * the given minimal match MM and the effective metric at the corresponding
00174    * points.
00175    */
00176   BCVspin_beta_placement_effmetric(MM, betaMin, betaMax, N, Sn, fmin, fmax,
00177                   effmetric_list, beta_list, &nbeta);
00178         
00179   /*
00180   printf("Num beta steps=%d\n", nbeta);
00181   */
00182   /*
00183    * There are nbeta levels of beta.
00184    * Next, obtain the psi0-psi3 bank at each value of beta
00185    */
00186         
00187   for(k=1; k<=nbeta; k++)
00188   {
00189           double a, b, c, det, q;
00190           int j, ndx;
00191   
00192           /* a, b, c are the three independent values of the metric
00193            */
00194           a = metric.G00 = effmetric_list[1][1][k];
00195           b = metric.G01 = effmetric_list[1][2][k];
00196           c = metric.G11 = effmetric_list[2][2][k];
00197 
00198           
00199           /* Diagonalize the metric and store the diagonalized values in the metric */
00200   
00201           det = a * c - b * b;
00202           q = sqrt( (a-c)*(a-c) + 4. * b*b );
00203           metric.g00 = 0.5 * (a + c - q);
00204           metric.g11 = 0.5 * (a + c + q);
00205 
00206         /*      THOMAS UPDATES !!!!!!!!!!! I have the feeling that the bank 
00207                 is over efficiency by a factor 3 with respect to classical
00208                 BCV search. Here as a first go, I would use a factor of sqrt(3)
00209                 in the metric component, based on comparison between BCV bank 
00210                 and BCVspin bank ffor different MM form 0.8 to 0.97 which shows
00211                  a constant ration of 3.1 
00212         
00213         metric.g00/=sqrt(3.);
00214         metric.g11/=sqrt(3.);
00215         */
00216           if ( a == c )
00217           {
00218                   metric.theta = LAL_PI/2.;
00219           }
00220           else
00221           {
00222           /* metric->theta = 0.5 * atan(2.*b/(a-c)); We want to always 
00223            * measure the angle from the semi-major axis to the tau0 axis 
00224            * which is given by the following line as opposed to the line above
00225            */
00226                   metric.theta = atan( b / (metric.g00 - c) );
00227           }
00228 
00229           /* Now we are ready to call Thomas' BCV template bank code
00230            * to compute the psi0-psi3 values depending on the value of LowGM.
00231            */
00232 
00233           if (coarseIn->insidePolygon == True)
00234           {
00235                   LALInspiralCreateFlatBankS3S4 (status->statusPtr, list, &bankParams, *coarseIn);
00236           }
00237           else
00238           {
00239                   LALInspiralCreateFlatBank (status->statusPtr, list, &bankParams);
00240           }
00241           CHECKSTATUSPTR( status );
00242 
00243           /* Optionally output the metric on the screen
00244            */
00245           fprintf(stderr, "k=%d beta=%e g00=%e g11=%e theta=%e Nf=%d\n", 
00246                           k, beta_list[k], metric.g00, metric.g11, metric.theta, list->length);
00247 
00248           /* Create additional memory to add the psi0-psi3 values at the current 
00249            * value of beta to the psi0-psi3 values stored from previous values of beta.
00250            */
00251           ndx = list->length;
00252           totTemps += ndx;
00253           totList->data = (REAL4 *) LALRealloc( totList->data, (3*totTemps) * sizeof(REAL4) );
00254                       
00255           if ( !totList->data )
00256           {
00257                   ABORT(status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM);
00258           }
00259           for (j=0; j<ndx; j++)
00260           {
00261                   int m1 = 2*j;
00262                   int m2 = 3*j + 3*totTemps-3*ndx;
00263                   totList->data[m2+0] = list->data[m1+0];
00264                   totList->data[m2+1] = list->data[m1+1];
00265                   totList->data[m2+2] = (float) (beta_list[k]);
00266                   /*
00267                   printf("%e %e %e %e\n", 
00268                   totList->data[m2], totList->data[m2+1], totList->data[m2+2], x); 
00269                   */
00270           }
00271   }
00272   /*
00273   for (k=0; k<totTemps; k++)
00274   {
00275           printf("%e %e %e\n", totList->data[3*k], totList->data[3*k+1], totList->data[3*k+2]); 
00276   }
00277   */
00278     
00279   /* Convert output data structure. */
00280  
00281   tmpBank = bank = (SnglInspiralTable *) LALCalloc(1, sizeof(SnglInspiralTable));
00282   if (bank == NULL){
00283           ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
00284   }
00285   *tiles = bank;
00286   for( k = 0; k < totTemps; k++ )
00287   {
00288           bank = bank->next = (SnglInspiralTable *) LALCalloc( 1, sizeof( SnglInspiralTable ) );
00289           if (bank == NULL)
00290           {
00291                   ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
00292           }
00293           bank->psi0 = totList->data[3*k+0];
00294           bank->psi3 = totList->data[3*k+1];
00295           bank->beta = totList->data[3*k+2];
00296           bank->f_final = fmax;
00297   }
00298     
00299   /* Free tiles template, which is blank. */
00300     
00301   *ntiles = totTemps;
00302   bank = (*tiles)->next;
00303   LALFree( *tiles );
00304   *tiles = bank;
00305 
00306   if (newSn.length!=0)
00307   {
00308         LALFree(newSn.data);
00309   }
00310 
00311   LALFree (totList->data);
00312   LALFree (list->data);
00313   LALFree (totList);
00314   LALFree (list);
00315   DETATCHSTATUSPTR(status);
00316   RETURN (status);
00317 }
00318 
00319 
00320 
00321 /* BCVspin_metric_fit.c    (by H.Tagoshi and H.Takahashi)
00322 
00323    The program to calculate the metric. 
00324    This routine requre Numerical Recipes library.
00325 
00326    The one sided noise power spectrum density Sn is
00327    array Sn[0..N]. The frequency interval, df, is df=fmax/N.
00328    Sn[0] is for f=0 [Hz]. Sn[N] is for f=fmax [Hz]. 
00329    Sn[i] must be non-zero from i=fmin/df to i=N. 
00330 
00331    The metric is given as bcv2metric[1..3][1..3]
00332    by BCVspin_metric() routine. 
00333    The index 1 is psi_0, index 2 is psi_3/2,
00334    and index 3 is beta. 
00335 
00336    At ver3.1, this program is working with gcc, 
00337    and PGI C compiler (pgcc) 
00338    (although a lot of warning message appear by pgcc). 
00339    However, this does not work with Intel C Compiler(IA32).
00340    Thus, this must be compliled by gcc (and probably by PGI C).
00341 
00342    2004/9/22 Revised version for metric part.
00343 
00344    2005/3/7  ver3.0 spacing part added.
00345 
00346    2005/3/21 ver3.1 bug fix
00347 
00348     2006/2/23 ver6.5 NR functions was replaced with GSL functions
00349 
00350 */
00351 
00352 #ifndef _HT_BCVSPINMETRIC_C_
00353 #define _HT_BCVSPINMETRIC_C_
00354 
00355 #define PI (3.141592653589793238462643383279502)
00356 
00357 #define DTRENORM (200)  /* The renormalization factor for the time derivative 
00358                            of the template. This is introduced to have 
00359                            an agreement with Yanbei's mathematica code. 
00360                            This value does not affect the results.
00361                            This can be set to 1. */
00362 #define N_RANDOM (100)  /* The number of monte carlo to generate 
00363                            the 6 phase factor */
00364 #define JJ (150)       /* The number of direction of contour 
00365                            for which the fitting is done. */
00366 
00367 double cont_data[JJ+1][4];
00368 
00369 int cos_sin_func(/* input */
00370                  int N, double beta,double fmax,
00371                  /* output */
00372                  double *costerm,double *sinterm)
00373 {
00374   int i;
00375   double df,freq,freq2;
00376 
00377   df=fmax/N;
00378 
00379   costerm[0]=0.; sinterm[0]=0.;
00380   for(i=1;i<=N;i++){
00381     freq=df*i;
00382     freq2=pow(freq,-2/3.);
00383     costerm[i]=cos(beta*freq2);
00384     sinterm[i]=sin(beta*freq2);
00385   }
00386   
00387   return 0;
00388 }
00389 
00390 int coef_A(/* input */
00391            int N,double *costerm,double *sinterm,double fmax,
00392            /* output */
00393            double *A1, double *A2,double *A3)
00394 {
00395   int i;
00396   double df,freq;
00397 
00398   df=fmax/N;
00399 
00400   A1[0]=0.;A2[0]=0.;A3[0]=0.;
00401   for(i=1;i<=N;i++){
00402     freq=df*i;
00403     A1[i]=pow(freq,-7/6.);
00404     A2[i]=A1[i]*costerm[i];
00405     A3[i]=A1[i]*sinterm[i];
00406   }
00407   
00408   return 0;
00409 }
00410 
00411 
00412 int deriv_A(/* input */
00413             int N,double *costerm,double *sinterm,double fmax,
00414             /* output */
00415             double *dA2,double *dA3)
00416 {
00417   int i;
00418   double df,freq,freq2;
00419 
00420   df=(fmax)/N;
00421 
00422   dA2[0]=0.;dA3[0]=0.;
00423   for(i=1;i<=N;i++){
00424     freq=df*i;
00425     freq2=pow(freq,-11/6.);
00426     dA2[i]=-freq2*sinterm[i];
00427     dA3[i]=freq2*costerm[i];
00428   }
00429   
00430   return 0;
00431 }
00432 
00433 /* inner product of real functions A(f) and B(f).
00434    A[0...N], B[0...N]
00435 */
00436 
00437 int innerR(/* input */
00438            int N, double *A, double *B, double *Sn,double fmin,double fmax,
00439            /* output */
00440            double *result)
00441 {
00442 
00443   int i,imin;
00444   double df,tmp;
00445 
00446   df=(fmax)/N;
00447   imin=fmin/df;
00448 
00449   tmp=(A[imin]*B[imin]/Sn[imin]+A[N]*B[N]/Sn[N])/2.;
00450   for(i=imin+1;i<N;i++)
00451     tmp+=A[i]*B[i]/Sn[i];
00452 
00453   *result=tmp*4*df;
00454 
00455   return 0;
00456 }
00457 
00458 /* inner product of complex functions A(f) and B(f).
00459    A[0...N], B[0...N]
00460 */
00461 
00462 int innerC(/* input */
00463            int N, dcomplex *A, dcomplex *B, double *Sn,double fmin,double fmax,
00464            /* output */
00465            double *result)
00466 {
00467 
00468   int i,imin;
00469   double df,tmp;
00470 
00471   df=(fmax)/N;
00472   imin=fmin/df;
00473 
00474   tmp = (A[imin].r * (B[imin].r) + A[imin].i * (B[imin].i))/Sn[imin]/2.;
00475   tmp+= (A[N].r * B[N].r + A[N].i * B[N].i)/Sn[N]/2.;
00476 
00477   for(i=imin+1;i<N;i++){
00478     /* here we take the multiplication of conjuguate of A by B and keep only the real part.*/
00479     tmp+= (A[i].r * B[i].r + A[i].i * B[i].i)/Sn[i];
00480   }
00481   *result=tmp*df*4;
00482   return 0;
00483 }
00484 
00485 
00486 int orthonormalized_A(/* input */
00487                       int N,double *A1, double *A2,double *A3,double *Sn,
00488                       double fmin,double fmax,
00489                       /* output */
00490                       double *tA2,double *tA3,
00491                       double *hA1,double *hA2, double *hA3,
00492                       double *normtA2,double *normtA3)
00493 {
00494   int i;
00495   double tmp,a,b,d;
00496   double A1A1,A1A2,A1A3,hA2A3;
00497 
00498   innerR(N,A1,A1,Sn,fmin,fmax,&A1A1);
00499   innerR(N,A1,A2,Sn,fmin,fmax,&A1A2);
00500   innerR(N,A1,A3,Sn,fmin,fmax,&A1A3);
00501 
00502   a=sqrt(A1A1);
00503   for(i=0;i<=N;i++)
00504     hA1[i]=A1[i]/a;
00505 
00506   b=A1A2/a;
00507   for(i=0;i<=N;i++){
00508     tA2[i]=A2[i]-b*hA1[i];
00509   }
00510 
00511   innerR(N,tA2,tA2,Sn,fmin,fmax,&tmp);
00512   *normtA2=sqrt(tmp);  
00513 
00514   for(i=0;i<=N;i++)
00515     hA2[i]=tA2[i]/(*normtA2);
00516 
00517   innerR(N,hA2,A3,Sn,fmin,fmax,&hA2A3);
00518 
00519   d=A1A3/a;
00520   for(i=0;i<=N;i++){
00521     tA3[i]=A3[i]-d*hA1[i]-hA2A3*hA2[i];
00522   }
00523 
00524   innerR(N,tA3,tA3,Sn,fmin,fmax,&tmp);
00525   *normtA3=sqrt(tmp);  
00526 
00527   for(i=0;i<=N;i++)
00528     hA3[i]=tA3[i]/(*normtA3);
00529 
00530   return 0;
00531 }
00532 
00533 int dA2dbeta(/* input */
00534              int N,double *Sn,double fmin,double fmax, double *hA1,
00535              double *tA2,double *dA2,double normtA2,
00536              /* output */
00537              double *dhA2)
00538 {
00539   int i;
00540   double inner,inner2,*dtA2, norm;
00541 
00542   dtA2 = (double *) malloc(sizeof(double) *(N+1));
00543   innerR(N,dA2,hA1,Sn,fmin,fmax,&inner);
00544 
00545   for(i=0;i<=N;i++)
00546     dtA2[i]=dA2[i]-inner*hA1[i];
00547 
00548   innerR(N,tA2,dtA2,Sn,fmin,fmax,&inner2);
00549   
00550   norm = pow(normtA2, 3.);
00551   for(i=0;i<=N;i++)
00552     dhA2[i]=dtA2[i]/normtA2-tA2[i]*inner2/norm;
00553 
00554   free(dtA2);
00555   return 0;
00556 }
00557 
00558 int dA3dbeta(/* input */
00559              int N,double *Sn,double fmin,double fmax,
00560              double *hA1,double *hA2,double *dhA2,
00561              double *A3,double *tA3,double *dA3,double normtA3,
00562              /*  output */
00563              double *dhA3)
00564 {
00565   int i;
00566   double inner,dhA2A3,hA2A3,*dtA3;
00567   double hA1dA3,hA2dA3, norm;
00568 
00569   dtA3 = (double *) malloc(sizeof(double)*(N+1));
00570 
00571   innerR(N,hA1,dA3,Sn,fmin,fmax,&hA1dA3);
00572 
00573   innerR(N,hA2,dA3,Sn,fmin,fmax,&hA2dA3);
00574 
00575   innerR(N,dhA2,A3,Sn,fmin,fmax,&dhA2A3);
00576 
00577   innerR(N,hA2,A3,Sn,fmin,fmax,&hA2A3);
00578 
00579   for(i=0;i<=N;i++)
00580     dtA3[i]=dA3[i]-hA1dA3*hA1[i]-hA2dA3*hA2[i]-dhA2A3*hA2[i]-
00581       hA2A3*dhA2[i];
00582 
00583   innerR(N,tA3,dtA3,Sn,fmin,fmax,&inner);
00584   norm = pow(normtA3, 3.);
00585   for(i=0;i<=N;i++)
00586     dhA3[i]=dtA3[i]/normtA3-tA3[i]*inner/norm;
00587 
00588   free(dtA3);
00589   return 0;
00590 }
00591 
00592 /* calc_function_G */
00593 /* A1,A2,A3 must be orthonormalized */
00594 /* dhA2db=d(A2)/d(beta), d() is pertial derivative */
00595 /* funcG[][][][] :  function G_{ij\alpha\beta} */
00596 
00597 int calc_function_G(/* input */
00598                int N,double *Sn,double fmin,double fmax,
00599                double *A1,double *A2,double *A3,
00600                double *dhA2db,double *dhA3db,
00601                /* output */
00602                double funcG[7][7][4][4])
00603 {
00604   int i,j,k,l,m,imin;
00605   double freq,df,*freq2,sum;
00606   double inn1[7][7][4][4],inn2[7][7][4];
00607 
00608 
00609   /*
00610   dcomplex u[7][4][N+1],A[7][N+1],ctmp;
00611   */
00612   dcomplex *u[7][4],*A[7],ctmp;
00613 
00614   for(i=0;i<=6;i++)
00615   for(j=0;j<=3;j++)
00616   {
00617      u[i][j] = (dcomplex *) malloc(sizeof(dcomplex)*(N+1));
00618   }
00619   for(i=0;i<=6;i++)
00620   {
00621      A[i] = (dcomplex *) malloc(sizeof(dcomplex)*(N+1));
00622   }
00623 
00624   df=(fmax)/N;
00625   imin=fmin/df;
00626   
00627   for(i=0;i<=N;i++){
00628     A[1][i]=DComplex(A1[i],0.);
00629     A[2][i]=DComplex(A2[i],0.);
00630     A[3][i]=DComplex(A3[i],0.);
00631     A[4][i]=DComplex(0.,A1[i]);
00632     A[5][i]=DComplex(0.,A2[i]);
00633     A[6][i]=DComplex(0.,A3[i]);
00634   }
00635  
00636   for(j=1;j<=6;j++){
00637     for(i=0;i<=N;i++){
00638       freq=df*i;
00639       ctmp=DComplex(0.,2*PI*freq/DTRENORM);
00640       u[j][0][i]=DCmul(ctmp,A[j][i]);
00641     }
00642   }
00643 
00644   for(i=0;i<=N;i++){
00645     u[1][3][i]=DComplex(0.,0.);
00646     u[2][3][i]=DComplex(dhA2db[i],0.);
00647     u[3][3][i]=DComplex(dhA3db[i],0.);
00648     u[4][3][i]=DComplex(0.,0.);
00649     u[5][3][i]=DComplex(0.,dhA2db[i]);
00650     u[6][3][i]=DComplex(0.,dhA3db[i]);
00651   }
00652 
00653   freq2 = (double *) malloc(sizeof(double)*(N+1));
00654   freq2[0]=0.;
00655   for(i=1;i<=N;i++){
00656     freq=df*i;
00657     freq2[i]=pow(freq,-5./3.);
00658   }
00659   
00660   for(j=1;j<=6;j++){
00661     for(i=0;i<=N;i++){
00662       ctmp=DComplex(0.,freq2[i]);
00663       u[j][1][i]=DCmul(ctmp,A[j][i]);
00664     }
00665   }
00666 
00667   freq2[0]=0.;
00668   for(i=1;i<=N;i++){
00669     freq=df*i;
00670     freq2[i]=pow(freq,-2./3.);
00671   }
00672   for(j=1;j<=6;j++){
00673     for(i=0;i<=N;i++){
00674       ctmp=DComplex(0.,freq2[i]);
00675       u[j][2][i]=DCmul(ctmp,A[j][i]);
00676     }
00677   }
00678   free(freq2);
00679 
00680   for(i=1;i<=6;i++)
00681     for(j=1;j<=6;j++)
00682       for(k=0;k<=3;k++)
00683         for(l=0;l<=3;l++){
00684           innerC(N,u[i][k],u[j][l],Sn,fmin,fmax,&sum);
00685           inn1[i][j][k][l]=sum;
00686         }
00687 
00688   for(i=1;i<=6;i++)
00689     for(j=1;j<=6;j++)
00690       for(k=0;k<=3;k++){
00691         innerC(N,u[i][k],A[j],Sn,fmin,fmax,&sum);
00692         inn2[i][j][k]=sum;
00693       }
00694 
00695   for(i=1;i<=6;i++)
00696     for(j=1;j<=6;j++)
00697       for(k=0;k<=3;k++)
00698         for(l=0;l<=3;l++){
00699           sum=0;
00700           for(m=1;m<=6;m++)
00701             sum+=inn2[i][m][k]*inn2[j][m][l];
00702 
00703           funcG[i][j][k][l]=inn1[i][j][k][l]-sum;
00704         }
00705 
00706   for(i=0;i<=6;i++)
00707   for(j=0;j<=3;j++)
00708   {
00709      free(u[i][j]);
00710   }
00711   for(i=0;i<=6;i++)
00712   {
00713      free(A[i]);
00714   }
00715 
00716   return 0;
00717 }
00718 
00719 int functionG(/* input */
00720               int N,double beta,double *Sn,double fmin,double fmax,
00721               /* output */
00722               double funcG[7][7][4][4])
00723 {
00724   double *A1,*A2,*A3,*tA2,*tA3,*hA1,*hA2,*hA3;
00725   double *costerm,*sinterm;
00726   double *dA2,*dA3,*dhA2,*dhA3;
00727   double normtA2,normtA3;
00728   
00729 
00730   A1 = (double *) malloc(sizeof(double)*(N+1));
00731   A2 = (double *) malloc(sizeof(double)*(N+1));
00732   A3 = (double *) malloc(sizeof(double)*(N+1));
00733   dA2 = (double *) malloc(sizeof(double)*(N+1));
00734   dA3 = (double *) malloc(sizeof(double)*(N+1));
00735   costerm = (double *) malloc(sizeof(double)*(N+1));
00736   sinterm = (double *) malloc(sizeof(double)*(N+1));
00737 
00738   cos_sin_func(N,beta,fmax,costerm,sinterm);
00739   coef_A(N,costerm,sinterm,fmax,A1,A2,A3);
00740   deriv_A(N,costerm,sinterm,fmax,dA2,dA3);
00741 
00742   free(costerm);
00743   free(sinterm);
00744 
00745   tA2 = (double *) malloc(sizeof(double)*(N+1));
00746   tA3 = (double *) malloc(sizeof(double)*(N+1));
00747   hA1 = (double *) malloc(sizeof(double)*(N+1));
00748   hA2 = (double *) malloc(sizeof(double)*(N+1));
00749   hA3 = (double *) malloc(sizeof(double)*(N+1));
00750   dhA2 = (double *) malloc(sizeof(double)*(N+1));
00751   dhA3 = (double *) malloc(sizeof(double)*(N+1));
00752 
00753   orthonormalized_A(N,A1,A2,A3,Sn,fmin,fmax,tA2,tA3,hA1,hA2,hA3,
00754                     &normtA2,&normtA3);
00755   free(A1);
00756   free(A2);
00757 
00758   dA2dbeta(N,Sn,fmin,fmax,hA1,tA2,dA2,normtA2,dhA2);
00759   free(tA2);
00760   free(dA2);
00761 
00762   dA3dbeta(N,Sn,fmin,fmax,hA1,hA2,dhA2,A3,tA3,dA3,normtA3,dhA3);
00763   free(A3);
00764   free(dA3);
00765   free(tA3);
00766 
00767   calc_function_G(N,Sn,fmin,fmax,hA1,hA2,hA3,dhA2,dhA3,funcG);
00768 
00769   free(hA1);
00770   free(hA2);
00771   free(hA3);
00772   free(dhA2);
00773   free(dhA3);
00774 
00775   return 0;
00776 }
00777 
00778 int three_metric(/* input */
00779               double funcG[7][7][4][4],double *alpha,
00780               /* output */
00781               double metric3[4][4])
00782 {
00783   int i,j,l,m,a,b;
00784   double tmp1,tmp2,tmp3;
00785 
00786   tmp3=0;
00787   for(i=1;i<=6;i++)
00788     for(j=1;j<=6;j++)
00789       tmp3+=alpha[i]*alpha[j]*funcG[i][j][0][0];
00790 
00791   for(a=1;a<=3;a++)
00792     for(b=1;b<=3;b++){
00793 
00794       tmp1=0;
00795       for(i=1;i<=6;i++)
00796         for(j=1;j<=6;j++)
00797           tmp1+=alpha[i]*alpha[j]*funcG[i][j][a][b];
00798       
00799       tmp2=0;
00800       for(i=1;i<=6;i++)
00801         for(j=1;j<=6;j++)
00802           for(l=1;l<=6;l++)
00803             for(m=1;m<=6;m++)
00804               tmp2+=alpha[i]*alpha[j]*funcG[i][j][0][a]
00805                 *alpha[l]*alpha[m]*funcG[l][m][0][b];
00806       
00807       metric3[a][b]=0.5*(tmp1-tmp2/tmp3);
00808     }
00809 
00810   return 0;
00811 }
00812 
00813 int generate_fit_points(/*input*/double MinMatch, double funcG[7][7][4][4],
00814                         int ndata, 
00815                         /*output*/ double fit_point[JJ+1][4])
00816 {
00817   const gsl_rng_type * T;
00818   gsl_rng * r;
00819   int i,j,k;
00820   double x[4],xd[4],sum,alpha[7],metric3[4][4];
00821 
00822   /*  for(i=1;i<=6;i++)
00823     for(j=1;j<=6;j++)
00824       for(k=0;k<=3;k++)
00825         printf("%e %e %e %e\n",funcG[i][j][k][0],funcG[i][j][k][1],
00826         funcG[i][j][k][2],funcG[i][j][k][3]);*/
00827           
00828         gsl_rng_env_setup();
00829 
00830     T = gsl_rng_default;
00831      r = gsl_rng_alloc (T);
00832         
00833         
00834         gsl_matrix *a = gsl_matrix_alloc (3, 3);
00835         gsl_vector *eig = gsl_vector_alloc (3);
00836     gsl_matrix *V = gsl_matrix_alloc (3, 3);
00837         
00838   sum=0;
00839   for(i=1;i<=6;i++){
00840                 alpha[i]=gsl_rng_uniform_pos (r)-0.5;
00841                 sum+=alpha[i]*alpha[i];
00842   }
00843   sum=sqrt(sum);
00844   for(i=1;i<=6;i++){
00845     alpha[i]=alpha[i]/sum;
00846   }
00847   three_metric(funcG,alpha,metric3);
00848         
00849         
00850   for(i=1;i<=3;i++)
00851     for(j=1;j<=3;j++)
00852                         gsl_matrix_set (a, i-1, j-1,metric3[i][j]);
00853                 
00854         gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc (3);
00855   
00856    gsl_eigen_symmv (a, eig,V,w);
00857 
00858         gsl_eigen_symmv_free (w);
00859         
00860         matrix3_determinant_plus(V,eig);
00861                 
00862         for(i=1;i<=ndata;i++){
00863     x[1]=gsl_rng_uniform_pos (r)-0.5;
00864     x[2]=gsl_rng_uniform_pos (r)-0.5;
00865     x[3]=gsl_rng_uniform_pos (r)-0.5;
00866     sum=x[1]*x[1]+x[2]*x[2]+x[3]*x[3];
00867                 sum=sqrt(sum);
00868 
00869     xd[1]=x[1]/sum*sqrt((1.-MinMatch)/gsl_vector_get (eig, 0));
00870     xd[2]=x[2]/sum*sqrt((1.-MinMatch)/gsl_vector_get (eig, 1));
00871         xd[3]=x[3]/sum*sqrt((1.-MinMatch)/gsl_vector_get (eig, 2));
00872                 
00873     for(j=1;j<=3;j++){
00874       fit_point[i][j]=0;
00875       for(k=1;k<=3;k++)
00876         fit_point[i][j]+=gsl_matrix_get (V, j-1, k-1) *xd[k];
00877     }
00878   }
00879         
00880           gsl_rng_free (r);
00881         gsl_vector_free(eig);
00882         gsl_matrix_free(a);
00883         gsl_matrix_free(V);
00884         
00885         return 0;
00886 }
00887 
00888 int generate_metric_data(/* input */double MinMatch,
00889                          double funcG[7][7][4][4])
00890 {
00891   extern double cont_data[JJ+1][4];  
00892   int i,k,i2,j2;
00893   double x[4],maxr;
00894   double alpha[7],metric3[N_RANDOM+1][4][4],sum,rr[N_RANDOM+1],distance;
00895   double fit_point[JJ+1][4], norm;
00896   const gsl_rng_type * T;
00897   gsl_rng * r;
00898         
00899         
00900   generate_fit_points(MinMatch,funcG,JJ,fit_point);
00901         
00902         gsl_rng_env_setup();
00903 
00904   T = gsl_rng_default;
00905    r = gsl_rng_alloc (T);
00906         
00907   for(k=1;k<=N_RANDOM;k++){
00908     sum=0;
00909     for(i2=1;i2<=6;i2++){
00910                         alpha[i2]=gsl_rng_uniform_pos (r)-0.5;
00911                         sum+=alpha[i2]*alpha[i2];
00912     }
00913     sum=sqrt(sum);
00914     for(i2=1;i2<=6;i2++){
00915       alpha[i2]=alpha[i2]/sum;
00916     }
00917     three_metric(funcG,alpha,metric3[k]);
00918   }
00919  
00920   norm = sqrt(1.-MinMatch);
00921 
00922   for(i=1;i<=JJ;i++){
00923     x[1]=fit_point[i][1];
00924     x[2]=fit_point[i][2];
00925     x[3]=fit_point[i][3];
00926 
00927     for(k=1;k<=N_RANDOM;k++){
00928     distance=0;
00929     for(i2=1;i2<=3;i2++)
00930       for(j2=1;j2<=3;j2++)
00931         distance+=metric3[k][i2][j2]*x[i2]*x[j2];
00932     rr[k]=sqrt(distance);
00933     }
00934 
00935     maxr=rr[1];
00936     for(k=2;k<=N_RANDOM;k++)
00937       if(rr[k]>maxr) maxr=rr[k];
00938 
00939     cont_data[i][1]=x[1]/maxr*norm;
00940     cont_data[i][2]=x[2]/maxr*norm;
00941     cont_data[i][3]=x[3]/maxr*norm;
00942   }
00943         
00944         gsl_rng_free (r);
00945         
00946         return 0;
00947 }
00948 
00949 void model_func(double xx,double afunc[])
00950 {
00951   int i,j,k;
00952   double x[4];
00953   extern double cont_data[JJ+1][4];  
00954 
00955   x[1]=cont_data[(int)xx][1];
00956   x[2]=cont_data[(int)xx][2];
00957   x[3]=cont_data[(int)xx][3];
00958 
00959   k=1;
00960   for(i=1;i<=3;i++)
00961     for(j=1;j<=3;j++){
00962       afunc[k]=(x[i]*x[j]);
00963       k++;
00964     }
00965 
00966 }  
00967 
00968 int metric_by_fit(/* input */
00969                   double MinMatch,int ndata,
00970                   /* output */
00971                   double metric_fit[4][4])
00972 {
00973   int i,j,k,ma=9,ia[ma+1];
00974   double x[ndata+1],y[ndata+1],sig[ndata+1];
00975   double chisq; 
00976 
00977         gsl_matrix *u = gsl_matrix_alloc (ndata,ma);
00978         gsl_matrix *v = gsl_matrix_alloc (ma,ma);
00979         gsl_vector *w = gsl_vector_alloc (ma);
00980         gsl_vector *a= gsl_vector_alloc (ma);
00981           
00982   for(i=1;i<=ndata;i++){
00983     x[i]=i;
00984     y[i]=1.-MinMatch;
00985     sig[i]=1.;
00986   }
00987   for(i=1;i<=ma;i++){
00988     ia[i]=1.;
00989   }
00990 
00991   svdfit_d_test(x,y,sig,ndata,a,ma,u,v,w,&chisq,&model_func);
00992         
00993   k=1;
00994   for(i=1;i<=3;i++)
00995     for(j=1;j<=3;j++){
00996       metric_fit[i][j]=gsl_vector_get(a,k-1);
00997       k++;
00998     }
00999 
01000         gsl_vector_free(w);
01001         gsl_vector_free(a);
01002         gsl_matrix_free(u);
01003         gsl_matrix_free(v);
01004 
01005 
01006   return 0;
01007 }
01008 
01009 int rescale_metric(/*input*/double MinMatch, int ndata, double metric1[4][4],
01010                    /*output*/ double metric[4][4])
01011 {
01012   int i,j,k;
01013   double distance,dmin;
01014 
01015   dmin=100;
01016   for(k=1;k<=ndata;k++){
01017     distance=0;
01018     for(i=1;i<=3;i++)
01019       for(j=1;j<=3;j++)
01020         distance+=metric1[i][j]*cont_data[k][i]*cont_data[k][j];
01021     if(distance<dmin) dmin=distance;
01022   }
01023 
01024   for(i=1;i<=3;i++)
01025     for(j=1;j<=3;j++)
01026       metric[i][j]=metric1[i][j]*(1.-MinMatch)/dmin;
01027 
01028   return 0;
01029 }
01030 
01031 /* Calculate the BCVspin metric. 
01032    Input:
01033    MinMatch : The minimal match of the template space
01034    N            : The number of frequency bin between f=0..fmax .
01035    Sn[0...N]    : one sided power spectrum density of noise [1/sqrt[Hz]].
01036    fmin         : minimum frequency cutoff for Sn(f).
01037    fmax         : maximum frequency for Sn(f).
01038    beta         : beta value of BCVspin template.
01039    dbg          : debuging flag. if dbg=1, some internal information
01040                   will be displayed. Otherwise, nothing is displayed.
01041 
01042    Output:
01043    bcv2metric[1..3][1..3] 
01044                 : The metric of the BCVspin template.
01045                 : The coordinate system is (\psi_0,\psi_{3/2},\beta).
01046 */
01047 int BCVspin_metric(/*input*/
01048                 double MinMatch, int N,double *Sn,double fmin,double fmax,double beta,
01049                 /*output*/
01050                 double bcv2metric[4][4],int dbg)
01051 {
01052   extern double cont_data[JJ+1][4];
01053   int i,j;
01054   double funcG[7][7][4][4];
01055   double metric_data3[JJ+1][4];
01056   double metric_fit[4][4],metric_rescaled[4][4];
01057 
01058   functionG(N,beta,Sn,fmin,fmax,funcG);
01059 
01060   if(dbg==1) fprintf(stderr,"metric data .....................\n");
01061   generate_metric_data(MinMatch,funcG);
01062         
01063   for(i=1;i<=JJ;i++){
01064     metric_data3[i][1]=cont_data[i][1];
01065     metric_data3[i][2]=cont_data[i][2];
01066     metric_data3[i][3]=cont_data[i][3];
01067   }
01068 
01069   if(dbg==1) fprintf(stderr,"metric fit .....................\n");
01070 
01071   metric_by_fit(MinMatch,JJ,metric_fit);
01072 
01073   if(dbg==1) 
01074     for(i=1;i<=3;i++)
01075       fprintf(stderr,"%e %e %e\n",
01076               metric_fit[i][1],metric_fit[i][2],metric_fit[i][3]);
01077 
01078   rescale_metric(MinMatch,JJ,metric_fit,metric_rescaled);
01079 
01080   for(i=1;i<=3;i++)
01081     for(j=i;j<=3;j++)
01082       bcv2metric[i][j]=metric_rescaled[i][j];
01083   for(i=2;i<=3;i++)
01084     for(j=1;j<=i-1;j++)
01085       bcv2metric[i][j]=metric_rescaled[j][i];
01086 
01087   return 0;
01088 }
01089 
01090 /* determinant of 3x3 matrix a[1..3][1..3] */
01091 
01092 double determinant3(gsl_matrix *matrix)
01093 {
01094         int i,j;
01095   double tmp, a[4][4];
01096         
01097         for (i = 0; i < 3; i++){
01098                 for (j = 0; j < 3; j++){
01099                         a[i+1][j+1]= gsl_matrix_get (matrix, i, j);
01100                 }
01101         }
01102   tmp=a[1][1]*a[2][2]*a[3][3];
01103   tmp+=a[1][2]*a[2][3]*a[3][1];
01104   tmp+=a[1][3]*a[2][1]*a[3][2];
01105   tmp-=a[1][3]*a[2][2]*a[3][1];
01106   tmp-=a[1][2]*a[2][1]*a[3][3];
01107   tmp-=a[1][1]*a[2][3]*a[3][2];
01108 
01109   return tmp;
01110 
01111 }
01112 
01113 int matrix2_determinant_plus(gsl_matrix *matrix,gsl_vector *eig)
01114 {
01115   int i,j;
01116   double a[3][3],det;
01117         
01118         for (i = 0; i < 2; i++){
01119                 for (j = 0; j < 2; j++){
01120                         a[i+1][j+1]= gsl_matrix_get (matrix, i, j);
01121                 }
01122         }
01123         
01124   det=a[1][1]*a[2][2]-a[1][2]*a[2][1];
01125 
01126   if(det<0){
01127                 
01128                 gsl_matrix *V = gsl_matrix_alloc (2, 2);
01129                 gsl_vector *v= gsl_vector_alloc (2);
01130                 
01131                 for (i = 0; i < 2; i++){
01132       gsl_vector_set (v, i, gsl_vector_get(eig, i));
01133                 }
01134                 
01135         for (i = 0; i < 2; i++){
01136                 for (j = 0; j < 2; j++){
01137                         gsl_matrix_set (V, i, j,gsl_matrix_get (matrix, i, j));
01138                 }
01139                 }
01140                 
01141                         
01142                    gsl_vector_set (eig, 0, gsl_vector_get(v, 1));
01143                 gsl_vector_set (eig, 1, gsl_vector_get(v, 0));
01144                 
01145                         
01146                 for(j=0;j<2;j++){
01147                         gsl_matrix_set (matrix, j, 0,gsl_matrix_get (V, j, 1));
01148                         gsl_matrix_set (matrix, j, 1,gsl_matrix_get (V, j, 0));
01149                 }
01150                 
01151     gsl_matrix_free(V);
01152     gsl_vector_free(v);
01153         }
01154         
01155   return 0;
01156 }
01157 
01158 int matrix3_determinant_plus(gsl_matrix *matrix,gsl_vector *eig)
01159 {
01160   int i,j;
01161   double det;
01162 
01163 
01164   det=determinant3(matrix);
01165 
01166   if(det<0){
01167                 gsl_matrix *V = gsl_matrix_alloc (3, 3);
01168                 gsl_vector *v= gsl_vector_alloc (3);
01169                 
01170                 for (i = 0; i < 3; i++){
01171       gsl_vector_set (v, i, gsl_vector_get(eig, i));
01172                 }
01173                 
01174                 for (i = 0; i < 3; i++){
01175                 for (j = 0; j < 3; j++){
01176                         gsl_matrix_set (V, i, j,gsl_matrix_get (matrix, i, j));
01177                 }
01178                 }
01179                 
01180                 
01181                     gsl_vector_set (eig, 0, gsl_vector_get(v, 0));
01182                         gsl_vector_set (eig, 1, gsl_vector_get(v, 2));
01183                 gsl_vector_set (eig, 2, gsl_vector_get(v, 1));
01184                                 
01185                 for(j=0;j<3;j++){
01186                         gsl_matrix_set (matrix, j, 0,gsl_matrix_get (V, j, 0));
01187                         gsl_matrix_set (matrix, j, 1,gsl_matrix_get (V, j, 2));
01188                     gsl_matrix_set (matrix, j, 2,gsl_matrix_get (V, j, 1));
01189                 }
01190         
01191     gsl_matrix_free(V);
01192     gsl_vector_free(v);
01193         }
01194 
01195   return 0;
01196 }
01197 
01198 
01199 /* Compute the inner product of two vectors */
01200 double innerp(int n,double *b,double *c)
01201 {
01202   int i;
01203   double sum;
01204 
01205   sum=0.;
01206   for(i=1;i<=n;i++)
01207     sum+=b[i]*c[i];
01208 
01209   return sum;
01210 }
01211 
01212 /* Compute the 3-dim vector product */
01213 double vector_product(double *a,double *b,double *c)
01214 {
01215   a[1]=b[2]*c[3]-b[3]*c[2];
01216   a[2]=b[3]*c[1]-b[1]*c[3];
01217   a[3]=b[1]*c[2]-b[2]*c[1];
01218 
01219   return 0;
01220 }
01221 
01222 
01223 /* compute the product of matrix, B and C, BC. Result is A*/
01224 int product_matrix(int n,double A[][n+1],double B[][n+1],double C[][n+1])
01225 {
01226   int i,j;
01227   double b[4][4],c[4][4];
01228 
01229   for(i=1;i<=n;i++)
01230     for(j=1;j<=n;j++){
01231       b[i][j]=B[i][j];
01232       c[i][j]=C[j][i];
01233     }
01234 
01235   for(i=1;i<=n;i++)
01236     for(j=1;j<=n;j++)
01237       A[i][j]=innerp(n,b[i],c[j]);
01238 
01239   return 0;
01240 }
01241 
01242 /*Compute the product of a matrix A and a vector v, Av. Result is *w */
01243 int product_mat_vec(int n,double *w,double A[][n+1],double *v)
01244 {
01245   int i,j;
01246 
01247   for(i=1;i<=n;i++){
01248     w[i]=0;
01249     for(j=1;j<=n;j++)