LALInspiralBCVSpinRandomBank.c

Go to the documentation of this file.
00001 /*  <lalVerbatim file="LALInspiralBCVSpinBankCV">
00002 Authors: Ian Harry, B.S. Sathyaprakash,  Chris Van Den Broeck
00003 $Id: LALInspiralBCVSpinRandomBank.c,v 1.4 2008/03/13 16:05:44 sathya Exp $
00004 </lalVerbatim>  */
00005 /*  <lalLaTeX>
00006 \subsection{Module \texttt{LALInspiralBCVSpinRandomBank.c}}
00007 This code uses the random bank developed by I. Harry, B. Allen and B.S. Sathyaprakash (2007, in preparation).
00008 \subsubsection*{Prototypes}
00009 \subsubsection*{Description}
00010 \subsubsection*{Algorithm}
00011 \subsubsection*{Uses}
00012 \begin{verbatim}
00013 \end{verbatim}
00014 \subsubsection*{Notes}
00015 \clearpage
00016 </lalLaTeX>  */
00017 
00018 
00019 #include <math.h>
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 
00024 #include <lal/AVFactories.h>
00025 #include <lal/FlatMesh.h>
00026 #include <lal/LALConfig.h>
00027 #include <lal/LALConstants.h>
00028 #include <lal/LALDatatypes.h>
00029 #include <lal/LALInspiralBank.h>
00030 #include <lal/LALMalloc.h>
00031 #include <lal/LALStatusMacros.h>
00032 #include <lal/LALStdlib.h>
00033 #include <lal/LIGOMetadataTables.h>
00034 #include <lal/SeqFactories.h>
00035 #include <gsl/gsl_linalg.h>
00036 #include <time.h>
00037 #include <lal/LALInspiralRandomBank.h>
00038 #include <lal/LALSBBH-Metric.h>
00039 
00040 
00041 NRCSID(LALINSPIRALBCVSPINRANDOMBANKC, "$Id: LALInspiralBCVSpinRandomBank.c,v 1.4 2008/03/13 16:05:44 sathya Exp $");
00042 
00043 /* <lalVerbatim file="LALInspiralBCVSpinRandomBankCP"> */
00044 void
00045 LALInspiralBCVSpinRandomBank(
00046     LALStatus            *status,
00047     SnglInspiralTable    **tiles,
00048     INT4                 *ntiles,
00049     InspiralCoarseBankIn *coarseIn
00050     )
00051 /* </lalVerbatim> */
00052 
00053 {
00054   INT4 ShMaxSz, N, i, j, k;
00055   double *Sn;
00056   REAL8Vector newSn;
00057   MCBankIn bankIn;
00058   float *MCbank;
00059   SnglInspiralTable *bank=NULL;
00060   MetricFunc *thisMetric;
00061         
00062   INITSTATUS(status, "LALInspiralBCVSpinRandomBank", LALINSPIRALBCVSPINRANDOMBANKC );
00063   ATTATCHSTATUSPTR( status );
00064 
00065   ASSERT( coarseIn != NULL, status, LALINSPIRALBANKH_ENULL, LALINSPIRALBANKH_MSGENULL );
00066   ASSERT( *tiles == NULL, status, LALINSPIRALBANKH_ENULL, LALINSPIRALBANKH_MSGENULL );
00067 
00068   /* 
00069    * coarseIn structure knows about the range of beta, psi0,
00070    * and psi3. It also provides the power spectrum of noise,
00071    * minimal match (in mmCoarse), upper and lower freq cutoffs.
00072    */
00073 
00074   thisMetric = &BCVSpinMetric;
00075 
00076   /* The seed should be initialized to a more meaningful random number! */
00077   bankIn.error = 0.;
00078   bankIn.seed = coarseIn->iseed;
00079   bankIn.dim=3;
00080   bankIn.verbose=0;
00081   bankIn.nIni=coarseIn->nTIni;
00082   ShMaxSz = coarseIn->ShMaxSz;
00083   /*
00084   EstimateNumberOfTemplates(thisMetric, &bankIn);
00085   */
00086   bankIn.nFin=0;
00087 
00088   bankIn.p = (float *) malloc(sizeof(float) * bankIn.dim);
00089   bankIn.pMax = (float *) malloc(sizeof(float) * bankIn.dim);
00090   bankIn.pMin = (float *) malloc(sizeof(float) * bankIn.dim);
00091 
00092         
00093   /* we will use a one-d array to store the bank. The convention is
00094    * that the first bankIn.dim-elements of bank store the coordinates of
00095    * the first template, the bankIn.dim+1 element is reserved for a tag to
00096    * indicate if the random template is retained or rejected. We
00097    * therefore use an initial array of size nIni*(bankIn.dim+1).  
00098    */
00099 
00100   MCbank = (float *) malloc(sizeof(float)*bankIn.nIni*(bankIn.dim+1));
00101 
00102   /* We first convert minimal match to maximum mismatch, as 
00103   the random bank uses the latter, and we multiply by a 
00104   factor of 2 because the Tagoshi metric gives an overefficient 
00105   bank. This corresponds to increasing the distance between 
00106   templates by a factor of sqrt(2). 
00107   */
00108 
00109   bankIn.MM=(1-coarseIn->mmCoarse)*2.;
00110   bankIn.pMin[0] = coarseIn->psi0Min;
00111   bankIn.pMax[0] = coarseIn->psi0Max;
00112   bankIn.pMin[1] = coarseIn->psi3Min;
00113   bankIn.pMax[1] = coarseIn->psi3Max;
00114   bankIn.pMin[2] = coarseIn->betaMin;
00115   bankIn.pMax[2] = coarseIn->betaMax;
00116 
00117   Sn = coarseIn->shf.data->data;
00118   N = coarseIn->shf.data->length-1;
00119   newSn.length=0;
00120   newSn.data=NULL;
00121 
00122 
00123 #if 1
00124   if (N>ShMaxSz)
00125   {
00126     int ratio, m;
00127     ratio = N/ShMaxSz;
00128     N = N / ratio;
00129     LALInfo(status,  "entering BCVSpin metric computation using the smooth PSD \n");
00130     newSn.length= N;
00131 
00132     newSn.data  = (REAL8*) LALCalloc(1, sizeof(REAL8) * (newSn.length+1));
00133     for (m=0; m<N; m++)
00134     {
00135       int l;
00136       for (l=0;l<ratio; l++)
00137       {
00138         newSn.data[m]+=  coarseIn->shf.data->data[m*ratio+l];
00139       }
00140     newSn.data[m]/=ratio;
00141     }
00142     newSn.data[N] = coarseIn->shf.data->data[N*ratio];
00143     Sn = newSn.data; 
00144      
00145   }
00146 else
00147 {
00148     LALInfo(status,  "entering BCVSpin metric computation using the whole PSD\n");
00149 }
00150 #endif
00151 
00152   bankIn.Npsd = N;
00153   bankIn.Sn = Sn;
00154   /* Call the routine to generate the bank */
00155   MonteCarloBank(thisMetric, &bankIn, MCbank);
00156 
00157 
00158         
00159   if (bankIn.verbose)
00160   {
00161     fprintf(stdout, "Numtemplates=%d MaxMismatch=%e\n", bankIn.nFin, bankIn.MM); 
00162     for (i=0; i<bankIn.nIni; i++)
00163     {
00164        if ((int)MCbank[i*(bankIn.dim+1)+bankIn.dim])
00165        {
00166          for (j=0; j<bankIn.dim; j++) fprintf(stdout, "%e ", MCbank[i*(bankIn.dim+1)+j]);
00167          fprintf(stdout, "\n");
00168        }
00169      }
00170    }
00171   /* Convert output data structure. */
00172 
00173   bank = (SnglInspiralTable *) LALCalloc(1, sizeof(SnglInspiralTable));
00174   if (bank == NULL){
00175           ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
00176   }
00177 
00178   *tiles = bank;
00179   
00180   for( k = 0; k < bankIn.nIni; k++ )
00181   {
00182           if ((int)MCbank[k*(bankIn.dim+1)+bankIn.dim])
00183           {
00184                   bank = bank->next = (SnglInspiralTable *) LALCalloc( 1, sizeof( SnglInspiralTable ) );
00185                   if (bank == NULL)
00186                   {
00187                           ABORT( status, LALINSPIRALBANKH_EMEM, LALINSPIRALBANKH_MSGEMEM );
00188                   }
00189                   bank->psi0 = MCbank[k*(bankIn.dim+1)];
00190                   bank->psi3 = MCbank[k*(bankIn.dim+1)+1];
00191                   bank->beta = MCbank[k*(bankIn.dim+1)+2];
00192           }
00193   }
00194     
00195   /* Free tiles template, which is blank. */
00196     
00197   *ntiles = bankIn.nFin;
00198   bank = (*tiles)->next;
00199   LALFree( *tiles ); 
00200   free(bankIn.pMax); 
00201   free(bankIn.pMin); 
00202   free(bankIn.p); 
00203 
00204   *tiles = bank;
00205 
00206   if (newSn.length!=0)
00207   {
00208         LALFree(newSn.data);
00209   }
00210 
00211   DETATCHSTATUSPTR(status);
00212   RETURN (status);
00213 }
00214 
00215 void MonteCarloBank(
00216                 MetricFunc metric,
00217                 MCBankIn *in, 
00218                 float *bank)
00219 {
00220         int i, j;
00221 
00222         in->error = 1;
00223 
00224         /* Call the function to create a random bank */
00225         CreateRandomBank(in, bank);
00226         if (in->verbose)
00227         {
00228                 for (i=0; i<in->nIni; i++)
00229                 {
00230                         for (j=0; j<in->dim; j++)
00231                                 fprintf(stdout, "%e ", bank[i*(in->dim+1)+j]);
00232                         fprintf(stdout, "\n");
00233                 }
00234                 fprintf(stdout, "nIni=%d\n", in->nIni);
00235         }
00236         
00237         /* Throw away unwanted templates */
00238         FilterRandomBank(metric, in, bank);
00239 
00240         /* If everything works well return with error=0 */
00241         in->error = 0;
00242         return;
00243 }       
00244 
00245 /*
00246 void EstimateNumberOfTemplates(
00247                 MetricFunc metric,
00248                 MCBankIn  *in)
00249 {
00250         return;
00251 }
00252 */
00253 
00254 
00255 void CreateRandomBank(
00256                 MCBankIn *in, 
00257                 float *bank)
00258 {
00259         int i, j, k;
00260         float e;
00261 
00262         srand(in->seed);
00263         for (i=0; i<in->nIni; i++)
00264         {
00265                 k = i*(in->dim+1);
00266                 for (j=0; j<in->dim; j++)
00267                 {
00268                         e = (float) rand()/(float) RAND_MAX;
00269                         bank[k+j] = in->pMin[j] + e*(in->pMax[j] - in->pMin[j]);
00270                 }
00271                 /* We shall choose the last element in the series for a tag
00272                  * to tell us whether or not the current template is rejected;
00273                  * To begin with every template is a member of the bank 
00274                  */
00275                 bank[k+in->dim] = 1;
00276         }
00277         return;
00278 }
00279 
00280 void FilterRandomBank(
00281                 MetricFunc metric,
00282                 MCBankIn *in, 
00283                 float *bank)
00284 {
00285         int i, j, m, dimp, dimpnIni, diag, sze;
00286         float dist, *x=NULL, *y=NULL, *gij=NULL;
00287 
00288         dimp = in->dim + 1;
00289         dimpnIni = dimp * in->nIni;
00290         in->nFin = in->nIni;
00291 
00292         sze = (int) (in->dim * (in->dim + 1))/2;
00293         metric(*in, &diag, gij);
00294         x = (float *) malloc(sizeof(float) * in->dim);
00295         y = (float *) malloc(sizeof(float) * in->dim);
00296 
00297         if (diag) 
00298                 gij = (float *) malloc(sizeof(float) * in->dim);
00299         else
00300                 gij = (float *) malloc(sizeof(float) * sze);
00301         /* outer loop over all seed points */
00302         for (i=0; i<dimpnIni; i+=dimp)
00303         {
00304                 if (bank[i+in->dim])
00305                 {
00306                 /* coordinates of first point */
00307                 for (j=0; j<in->dim; j++) x[j] = in->p[j] = bank[i+j]; 
00308                 /* compute the metric at the point (in->p) in question */
00309                 metric(*in, &diag, gij);
00310                 /* inner loop over test points */
00311                 for (m=i+dimp; m<dimpnIni; m+=dimp)
00312                 {
00313                         /* compute dist to current pt only if it is not already rejected */
00314                         if (bank[m+in->dim])
00315                         {
00316                                 /* coordinates of m-th point */
00317                                 for (j=0; j<in->dim; j++) 
00318                                 {
00319                                         y[j] = bank[m+j];
00320                                         if (in->verbose) fprintf(stdout, "%e %e %e ", x[j],y[j],gij[j]);
00321                                 }
00322                                 MCComputeDistance(in->dim, diag, x, y, gij, &dist);
00323                                 if (in->verbose) fprintf(stdout, "%e %d %d\n", dist, i, m);
00324 
00325                                 if (dist<in->MM) 
00326                                 {
00327                                         bank[m+in->dim] = 0;
00328                                         --(in->nFin);
00329                                 }
00330                         }
00331                 }
00332                 }
00333         }
00334         free(x);
00335         free(y);
00336         x = NULL;
00337         y = NULL;
00338         if (in->verbose) fprintf(stderr, "NoFinTmplts = %d\n", in->nFin);
00339         free(gij);
00340         gij = NULL;
00341         return;
00342 }
00343 
00344 void MCComputeDistance(
00345                 int   dim,
00346                 int   diag,
00347                 float *x, 
00348                 float *y, 
00349                 float *gij,
00350                 float *dist
00351                 )
00352 {
00353         int i, j, k;
00354         float dxi, dxj;
00355         *dist = 0.;
00356         k = 0;
00357         if (diag)
00358         {
00359                 for (i=0; i<dim; i++) 
00360                 {
00361                         dxi = x[i]-y[i];
00362                         *dist += gij[i] * dxi * dxi;
00363                 }
00364         }
00365         else
00366                 for (i=0; i<dim; i++)
00367                 {
00368                         dxi = x[i]-y[i];
00369                         *dist += gij[k] * dxi * dxi;
00370                         /* fprintf(stdout,"%d %d \n", i, k); */
00371                         for (j=i+1; j<dim; j++)
00372                         {
00373                                 /* fprintf(stdout,"%d %d %d %d \n", i, j, k, k+j-i); */
00374                                 dxj = x[j]-y[j];
00375                                 *dist += 2. * gij[k+j-i] * dxi *dxj;
00376                         }
00377                         k += dim - i; 
00378                 }
00379         return;
00380 }
00381 
00382 /*
00383 void BankStats(
00384                 MetricFunc metric,
00385                 MCBankIn *in, 
00386                 float *bank)
00387 {
00388         return;
00389 }
00390 */
00391 
00392 void SchwarzschildMetric(
00393                 MCBankIn in, 
00394                 int *diag, 
00395                 float *gij)
00396 {
00397         *diag = 1;
00398         if (gij==NULL) return;
00399         gij[0] = 1.-2./in.p[0];
00400         gij[1] = in.p[0]*in.p[0];
00401         gij[2] = in.p[0]*in.p[0] * pow(sin(in.p[1]),2.);
00402         return;
00403 }
00404 
00405 void TwoSphereMetric(
00406                 MCBankIn in, 
00407                 int *diag, 
00408                 float *gij)
00409 {
00410         *diag = 1;
00411         if (gij==NULL) return;
00412         gij[0] = 1;
00413         gij[1] = pow(sin(in.p[0]),2.);
00414         return;
00415 }
00416 
00417 void FlatSpaceMetric(
00418                 MCBankIn in, 
00419                 int *diag, 
00420                 float *gij)
00421 {
00422         int i;
00423         *diag = 1;
00424         if (gij==NULL) return;
00425         for (i=0; i<in.dim; i++) gij[i] = 1;
00426         return;
00427 }
00428 
00429 void TwoDFlatSpacePolarMetric(
00430                 MCBankIn in, 
00431                 int *diag, 
00432                 float *gij)
00433 {
00434         *diag = 1;
00435         if (gij==NULL) return;
00436         gij[0] = 1;
00437         gij[1] = in.p[0]*in.p[0];
00438         return;
00439 }
00440 
00441 #ifndef _HT_BCVSPINMETRIC_C_
00442 #define _HT_BCVSPINMETRIC_C_
00443 #define PI (3.141592653589793238462643383279502)
00444 #define DTRENORM (200)  /* The renormalization factor for the time derivative 
00445                            of the template. This is introduced to have 
00446                            an agreement with Yanbei's mathematica code. 
00447                            This value does not affect the results.
00448                            This can be set to 1. */
00449 #define N_RANDOM (100)  /* The number of monte carlo to generate 
00450                            the 6 phase factor */
00451 #define JJ (150)       /* The number of direction of contour 
00452                            for which the fitting is done. */
00453 double cont_data[JJ+1][4];
00454 
00455 void BCVSpinMetric(
00456                 MCBankIn in, 
00457                 int *diag, 
00458                 float *gij)
00459 {
00460         int dbg=0, dim=4, N, i;
00461         double MinMatch, fmin, fmax, beta, **bcv2metric=NULL;
00462 
00463         *diag = 0;
00464         if (gij==NULL) return;
00465 
00466         if ( (bcv2metric = (double **) malloc(sizeof(double*)*dim)) == NULL )
00467         {
00468                 bcv2metric = NULL;
00469                 return;
00470         }
00471 
00472         for (i=0; i<dim; i++)
00473         {
00474                 if ( (bcv2metric[i] = (double *) malloc(sizeof(double)*dim)) == NULL )
00475                 {
00476                         bcv2metric = NULL;
00477                         return;
00478                 }
00479         }
00480 
00481         N = (int)in.Npsd-1;
00482         beta = in.p[2];
00483         MinMatch = 1.- (double) in.MM;
00484         fmax = 1000.;
00485         fmin = 40.;
00486 
00487         BCVspin_metric(MinMatch, N, in.Sn, fmin, fmax, beta, bcv2metric, dbg);
00488         
00489         gij[0] = (float) bcv2metric[1][1];
00490         gij[1] = (float) bcv2metric[1][2];
00491         gij[2] = (float) bcv2metric[1][3];
00492         gij[3] = (float) bcv2metric[2][2];
00493         gij[4] = (float) bcv2metric[2][3];
00494         gij[5] = (float) bcv2metric[3][3];
00495 
00496         for (i=0; i<dim; i++)
00497         {
00498                 free(bcv2metric[i]); 
00499         }
00500         free(bcv2metric);
00501         return;
00502 }
00503 
00504 /* determinant of 3x3 matrix a[1..3][1..3] */
00505 
00506 static double determinant3BCVSpinRandomBank(gsl_matrix *matrix)
00507 {
00508         int i,j;
00509   double tmp, a[4][4];
00510         
00511         for (i = 0; i < 3; i++){
00512                 for (j = 0; j < 3; j++){
00513                         a[i+1][j+1]= gsl_matrix_get (matrix, i, j);
00514                 }
00515         }
00516   tmp=a[1][1]*a[2][2]*a[3][3];
00517   tmp+=a[1][2]*a[2][3]*a[3][1];
00518   tmp+=a[1][3]*a[2][1]*a[3][2];
00519   tmp-=a[1][3]*a[2][2]*a[3][1];
00520   tmp-=a[1][2]*a[2][1]*a[3][3];
00521   tmp-=a[1][1]*a[2][3]*a[3][2];
00522 
00523   return tmp;
00524 
00525 }
00526 
00527 
00528 int matrix3_determinant_plus(gsl_matrix *matrix,gsl_vector *eig)
00529 {
00530   int i,j;
00531   double det;
00532 
00533 
00534   det=determinant3BCVSpinRandomBank(matrix);
00535 
00536   if(det<0){
00537                 gsl_matrix *V = gsl_matrix_alloc (3, 3);
00538                 gsl_vector *v= gsl_vector_alloc (3);
00539                 
00540                 for (i = 0; i < 3; i++){
00541       gsl_vector_set (v, i, gsl_vector_get(eig, i));
00542                 }
00543                 
00544                 for (i = 0; i < 3; i++){
00545                 for (j = 0; j < 3; j++){
00546                         gsl_matrix_set (V, i, j,gsl_matrix_get (matrix, i, j));
00547                 }
00548                 }
00549                 
00550                 
00551                     gsl_vector_set (eig, 0, gsl_vector_get(v, 0));
00552                         gsl_vector_set (eig, 1, gsl_vector_get(v, 2));
00553                 gsl_vector_set (eig, 2, gsl_vector_get(v, 1));
00554                                 
00555                 for(j=0;j<3;j++){
00556                         gsl_matrix_set (matrix, j, 0,gsl_matrix_get (V, j, 0));
00557                         gsl_matrix_set (matrix, j, 1,gsl_matrix_get (V, j, 2));
00558                     gsl_matrix_set (matrix, j, 2,gsl_matrix_get (V, j, 1));
00559                 }
00560         
00561     gsl_matrix_free(V);
00562     gsl_vector_free(v);
00563         }
00564 
00565   return 0;
00566 }
00567 
00568 
00569 
00570 
00571 int three_metric(/* input */
00572               double funcG[7][7][4][4],double *alpha,
00573               /* output */
00574               double metric3[4][4])
00575 {
00576   int i,j,l,m,a,b;
00577   double tmp1,tmp2,tmp3;
00578 
00579   tmp3=0;
00580   for(i=1;i<=6;i++)
00581     for(j=1;j<=6;j++)
00582       tmp3+=alpha[i]*alpha[j]*funcG[i][j][0][0];
00583 
00584   for(a=1;a<=3;a++)
00585     for(b=1;b<=3;b++){
00586 
00587       tmp1=0;
00588       for(i=1;i<=6;i++)
00589         for(j=1;j<=6;j++)
00590           tmp1+=alpha[i]*alpha[j]*funcG[i][j][a][b];
00591       
00592       tmp2=0;
00593       for(i=1;i<=6;i++)
00594         for(j=1;j<=6;j++)
00595           for(l=1;l<=6;l++)
00596             for(m=1;m<=6;m++)
00597               tmp2+=alpha[i]*alpha[j]*funcG[i][j][0][a]
00598                 *alpha[l]*alpha[m]*funcG[l][m][0][b];
00599       
00600       metric3[a][b]=0.5*(tmp1-tmp2/tmp3);
00601     }
00602 
00603   return 0;
00604 }
00605 
00606 int generate_fit_points(/*input*/double MinMatch, double funcG[7][7][4][4],
00607                         int ndata, 
00608                         /*output*/ double **fit_point)
00609 {
00610   const gsl_rng_type * T;
00611   gsl_rng * r;
00612   int i,j,k;
00613   double x[4],xd[4],sum,alpha[7],metric3[4][4];
00614   gsl_matrix *a = gsl_matrix_alloc(3, 3);
00615   gsl_vector *eig = gsl_vector_alloc(3);
00616   gsl_matrix *V = gsl_matrix_alloc(3, 3);
00617   gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc (3);
00618         
00619   gsl_rng_env_setup();
00620   T = gsl_rng_default;
00621   r = gsl_rng_alloc (T);
00622         
00623         
00624   sum=0;
00625   for(i=1;i<=6;i++)
00626   {
00627           alpha[i]=gsl_rng_uniform_pos (r)-0.5;
00628           sum+=alpha[i]*alpha[i];
00629   }
00630   sum=sqrt(sum);
00631   for(i=1;i<=6;i++)
00632   {
00633           alpha[i]=alpha[i]/sum;
00634   }
00635   three_metric(funcG,alpha,metric3);
00636         
00637         
00638   for(i=1;i<=3;i++)
00639           for(j=1;j<=3;j++)
00640                   gsl_matrix_set (a, i-1, j-1,metric3[i][j]);
00641                 
00642   gsl_eigen_symmv (a, eig,V,w);
00643   gsl_eigen_symmv_free (w);
00644   matrix3_determinant_plus(V,eig);
00645                 
00646         
00647   for(i=1;i<=ndata;i++){
00648     x[1]=gsl_rng_uniform_pos (r)-0.5;
00649     x[2]=gsl_rng_uniform_pos (r)-0.5;
00650     x[3]=gsl_rng_uniform_pos (r)-0.5;
00651     sum=x[1]*x[1]+x[2]*x[2]+x[3]*x[3];
00652     sum=sqrt(sum);
00653     xd[1]=x[1]/sum*sqrt((1.-MinMatch)/gsl_vector_get (eig, 0));
00654     xd[2]=x[2]/sum*sqrt((1.-MinMatch)/gsl_vector_get (eig, 1));
00655     xd[3]=x[3]/sum*sqrt((1.-MinMatch)/gsl_vector_get (eig, 2));
00656     for(j=1;j<=3;j++){
00657       fit_point[i][j]=0;
00658       for(k=1;k<=3;k++)
00659         fit_point[i][j]+=gsl_matrix_get (V, j-1, k-1) *xd[k];
00660     }
00661   }
00662         
00663   gsl_rng_free (r);
00664   gsl_vector_free(eig);
00665   gsl_matrix_free(a);
00666   gsl_matrix_free(V);
00667         
00668         return 0;
00669 }
00670 
00671 /* inner product of real functions A(f) and B(f).
00672    A[0...N], B[0...N]
00673 */
00674 
00675 int innerR(/* input */
00676            int N, double *A, double *B, double *Sn,double fmin,double fmax,
00677            /* output */
00678            double *result)
00679 {
00680 
00681   int i,imin;
00682   double df,tmp;
00683 
00684   df=(fmax)/N;
00685   imin=fmin/df;
00686 
00687   tmp=(A[imin]*B[imin]/Sn[imin]+A[N]*B[N]/Sn[N])/2.;
00688   for(i=imin+1;i<N;i++)
00689     tmp+=A[i]*B[i]/Sn[i];
00690 
00691   *result=tmp*4*df;
00692 
00693   return 0;
00694 }
00695 
00696 /* inner product of complex functions A(f) and B(f).
00697    A[0...N], B[0...N]
00698 */
00699 
00700 int innerC(/* input */
00701            int N, dcomplex *A, dcomplex *B, double *Sn,double fmin,double fmax,
00702            /* output */
00703            double *result)
00704 {
00705 
00706   int i,imin;
00707   double df,tmp;
00708 
00709   df=(fmax)/N;
00710   imin=fmin/df;
00711 
00712   tmp = (A[imin].r * (B[imin].r) + A[imin].i * (B[imin].i))/Sn[imin]/2.;
00713   tmp+= (A[N].r * B[N].r + A[N].i * B[N].i)/Sn[N]/2.;
00714 
00715   for(i=imin+1;i<N;i++){
00716     /* here we take the multiplication of conjuguate of A by B and keep only the real part.*/
00717     tmp+= (A[i].r * B[i].r + A[i].i * B[i].i)/Sn[i];
00718   }
00719   *result=tmp*df*4;
00720   return 0;
00721 }
00722 
00723 int generate_metric_data(/* input */double MinMatch,
00724                          double funcG[7][7][4][4])
00725 {
00726         
00727   extern double cont_data[JJ+1][4];  
00728   int i,k,i2,j2;
00729   double x[4],maxr;
00730   double alpha[7],metric3[N_RANDOM+1][4][4],sum,rr[N_RANDOM+1],distance;
00731   double norm;
00732   const gsl_rng_type * T;
00733   gsl_rng * r;
00734   /*
00735   double fit_point[JJ+1][4];
00736   */
00737   double **fit_point;
00738         
00739         
00740 
00741   fit_point = (double **) malloc(sizeof(double *)*(JJ+1));
00742   for (i=0; i<4; i++)
00743   {
00744           fit_point[i] = (double *) malloc(sizeof(double) * 4);
00745   }
00746 
00747   generate_fit_points(MinMatch,funcG,JJ,fit_point);
00748         
00749         gsl_rng_env_setup();
00750 
00751   T = gsl_rng_default;
00752    r = gsl_rng_alloc (T);
00753         
00754   for(k=1;k<=N_RANDOM;k++){
00755     sum=0;
00756     for(i2=1;i2<=6;i2++){
00757                         alpha[i2]=gsl_rng_uniform_pos (r)-0.5;
00758                         sum+=alpha[i2]*alpha[i2];
00759     }
00760     sum=sqrt(sum);
00761     for(i2=1;i2<=6;i2++){
00762       alpha[i2]=alpha[i2]/sum;
00763     }
00764     three_metric(funcG,alpha,metric3[k]);
00765   }
00766  
00767   norm = sqrt(1.-MinMatch);
00768 
00769   for(i=1;i<=JJ;i++){
00770     x[1]=fit_point[i][1];
00771     x[2]=fit_point[i][2];
00772     x[3]=fit_point[i][3];
00773 
00774     for(k=1;k<=N_RANDOM;k++){
00775     distance=0;
00776     for(i2=1;i2<=3;i2++)
00777       for(j2=1;j2<=3;j2++)
00778         distance+=metric3[k][i2][j2]*x[i2]*x[j2];
00779     rr[k]=sqrt(distance);
00780     }
00781 
00782     maxr=rr[1];
00783     for(k=2;k<=N_RANDOM;k++)
00784       if(rr[k]>maxr) maxr=rr[k];
00785 
00786     cont_data[i][1]=x[1]/maxr*norm;
00787     cont_data[i][2]=x[2]/maxr*norm;
00788     cont_data[i][3]=x[3]/maxr*norm;
00789   }
00790         
00791         gsl_rng_free (r);
00792         
00793         return 0;
00794 }
00795 
00796 int rescale_metric(/*input*/double MinMatch, int ndata, double metric1[4][4],
00797                    /*output*/ double metric[4][4])
00798 {
00799   int i,j,k;
00800   double distance,dmin;
00801 
00802   dmin=100;
00803   for(k=1;k<=ndata;k++){
00804     distance=0;
00805     for(i=1;i<=3;i++)
00806       for(j=1;j<=3;j++)
00807         distance+=metric1[i][j]*cont_data[k][i]*cont_data[k][j];
00808     if(distance<dmin) dmin=distance;
00809   }
00810 
00811   for(i=1;i<=3;i++)
00812     for(j=1;j<=3;j++)
00813       metric[i][j]=metric1[i][j]*(1.-MinMatch)/dmin;
00814 
00815   return 0;
00816 }
00817 
00818 
00819 #define TOL 1.0e-10
00820 
00821 void svdfit_d_test(double x[], double y[], double sig[], int ndata, gsl_vector *a, int ma,
00822         gsl_matrix *u, gsl_matrix *v, gsl_vector *w, double *chisq,
00823         void (*funcs)(double, double []))
00824 {
00825         int j,i;
00826         double wmax,tmp,thresh,sum,*afunc;
00827         gsl_vector *b= gsl_vector_alloc (ndata);
00828         gsl_vector *ws= gsl_vector_alloc (ma);
00829         
00830         
00831         if ( (afunc = (double *)malloc(sizeof(double) * (ma+1))) == NULL)
00832         {
00833                 afunc = NULL;
00834                 gsl_vector_free(b);
00835                 gsl_vector_free(ws);
00836                 return;
00837         }
00838         for (i=1;i<=ndata;i++) {
00839                 (*funcs)(x[i],afunc);
00840                 tmp=1.0/sig[i];
00841                 for (j=1;j<=ma;j++) {
00842                         gsl_matrix_set(u,i-1,j-1,afunc[j]*tmp);
00843                 }
00844                 gsl_vector_set(b,i-1,y[i]*tmp);
00845         }
00846         
00847         gsl_linalg_SV_decomp (u, v,w, ws);
00848         
00849         wmax=0.0;
00850         for (j=1;j<=ma;j++)
00851                 if (gsl_vector_get(w,j-1) > wmax) wmax=gsl_vector_get(w,j-1) ;
00852         thresh=TOL*wmax;
00853         for (j=1;j<=ma;j++)
00854         if (gsl_vector_get(w,j-1)  < thresh) gsl_vector_set(w,j-1,0.0);
00855         
00856         
00857         gsl_linalg_SV_solve (u, v,w, b, a);
00858         
00859         *chisq=0.0;
00860         for (i=1;i<=ndata;i++) {
00861                 (*funcs)(x[i],afunc);
00862                 for (sum=0.0,j=1;j<=ma;j++) sum += gsl_vector_get(a, j-1)*afunc[j];
00863                 *chisq += (tmp=(y[i]-sum)/sig[i],tmp*tmp);
00864         }
00865         gsl_vector_free(b);
00866         gsl_vector_free(ws);
00867         free(afunc);
00868 }
00869 #undef TOL
00870 
00871 
00872 void model_func(double xx,double afunc[])
00873 {
00874   int i,j,k;
00875   double x[4];
00876   extern double cont_data[JJ+1][4];  
00877 
00878   x[1]=cont_data[(int)xx][1];
00879   x[2]=cont_data[(int)xx][2];
00880   x[3]=cont_data[(int)xx][3];
00881 
00882   k=1;
00883   for(i=1;i<=3;i++)
00884     for(j=1;j<=3;j++){
00885       afunc[k]=(x[i]*x[j]);
00886       k++;
00887     }
00888 
00889 }  
00890 
00891 int metric_by_fit(/* input */
00892                   double MinMatch,int ndata,
00893                   /* output */
00894                   double metric_fit[4][4])
00895 {
00896   int i, j, k, ma=9, *ia;
00897   double *x, *y, *sig;
00898   double chisq; 
00899         
00900   gsl_matrix *u = gsl_matrix_alloc (ndata,ma);
00901   gsl_matrix *v = gsl_matrix_alloc (ma,ma);
00902   gsl_vector *w = gsl_vector_alloc (ma);
00903   gsl_vector *a= gsl_vector_alloc (ma);
00904           
00905   if ( ( ia = (int *)    malloc(sizeof(int)*(ma+1)))  == NULL ||
00906        (  x = (double *) malloc(sizeof(double)*(ndata+1))) == NULL ||
00907        (  y = (double *) malloc(sizeof(double)*(ndata+1)))  == NULL ||
00908        (sig = (double *) malloc(sizeof(double)*(ndata+1)))  == NULL
00909      )
00910   {
00911           ia = NULL;
00912           x = y = sig = NULL;
00913           gsl_vector_free(w);
00914           gsl_vector_free(a);
00915           gsl_matrix_free(u);
00916           gsl_matrix_free(v);
00917           return 1;
00918   }
00919 
00920   for(i=1;i<=ndata;i++){
00921     x[i]=i;
00922     y[i]=1.-MinMatch;
00923     sig[i]=1.;
00924   }
00925   for(i=1;i<=ma;i++){
00926     ia[i]=1.;
00927   }
00928 
00929   svdfit_d_test(x,y,sig,ndata,a,ma,u,v,w,&chisq,&model_func);
00930         
00931   k=1;
00932   for(i=1;i<=3;i++)
00933     for(j=1;j<=3;j++){
00934       metric_fit[i][j]=gsl_vector_get(a,k-1);
00935       k++;
00936     }
00937 
00938   free(ia);
00939   free(x);
00940   free(y);
00941   free(sig);
00942   gsl_vector_free(w);
00943   gsl_vector_free(a);
00944   gsl_matrix_free(u);
00945   gsl_matrix_free(v);
00946 
00947   return 0;
00948 }
00949 int cos_sin_func(/* input */
00950                  int N, double beta,double fmax,
00951                  /* output */
00952                  double *costerm,double *sinterm)
00953 {
00954   int i;
00955   double df,freq,freq2;
00956 
00957   df=fmax/N;
00958 
00959   costerm[0]=0.; sinterm[0]=0.;
00960   for(i=1;i<=N;i++){
00961     freq=df*i;
00962     freq2=pow(freq,-2/3.);
00963     costerm[i]=cos(beta*freq2);
00964     sinterm[i]=sin(beta*freq2);
00965   }
00966   
00967   return 0;
00968 }
00969 
00970 int coef_A(/* input */
00971            int N,double *costerm,double *sinterm,double fmax,
00972            /* output */
00973            double *A1, double *A2,double *A3)
00974 {
00975   int i;
00976   double df,freq;
00977 
00978   df=fmax/N;
00979 
00980   A1[0]=0.;A2[0]=0.;A3[0]=0.;
00981   for(i=1;i<=N;i++){
00982     freq=df*i;
00983     A1[i]=pow(freq,-7/6.);
00984     A2[i]=A1[i]*costerm[i];
00985     A3[i]=A1[i]*sinterm[i];
00986   }
00987   
00988   return 0;
00989 }
00990 
00991 int dA2dbeta(/* input */
00992              int N,double *Sn,double fmin,double fmax, double *hA1,
00993              double *tA2,double *dA2,double normtA2,
00994              /* output */
00995              double *dhA2)
00996 {
00997   int i;
00998   double inner,inner2,*dtA2, norm;
00999 
01000   dtA2 = (double *) malloc(sizeof(double) *(N+1));
01001   innerR(N,dA2,hA1,Sn,fmin,fmax,&inner);
01002 
01003   for(i=0;i<=N;i++)
01004     dtA2[i]=dA2[i]-inner*hA1[i];
01005 
01006   innerR(N,tA2,dtA2,Sn,fmin,fmax,&inner2);
01007   
01008   norm = pow(normtA2, 3.);
01009   for(i=0;i<=N;i++)
01010     dhA2[i]=dtA2[i]/normtA2-tA2[i]*inner2/norm;
01011 
01012   free(dtA2);
01013   return 0;
01014 }
01015 
01016 int dA3dbeta(/* input */
01017              int N,double *Sn,double fmin,double fmax,
01018              double *hA1,double *hA2,double *dhA2,
01019              double *A3,double *tA3,double *dA3,double normtA3,
01020              /*  output */
01021              double *dhA3)
01022 {
01023   int i;
01024   double inner,dhA2A3,hA2A3,*dtA3;
01025   double hA1dA3,hA2dA3, norm;
01026 
01027   dtA3 = (double *) malloc(sizeof(double)*(N+1));
01028 
01029   innerR(N,hA1,dA3,Sn,fmin,fmax,&hA1dA3);
01030 
01031   innerR(N,hA2,dA3,Sn,fmin,fmax,&hA2dA3);
01032 
01033   innerR(N,dhA2,A3,Sn,fmin,fmax,&dhA2A3);
01034 
01035   innerR(N,hA2,A3,Sn,fmin,fmax,&hA2A3);
01036 
01037   for(i=0;i<=N;i++)
01038     dtA3[i]=dA3[i]-hA1dA3*hA1[i]-hA2dA3*hA2[i]-dhA2A3*hA2[i]-
01039       hA2A3*dhA2[i];
01040 
01041   innerR(N,tA3,dtA3,Sn,fmin,fmax,&inner);
01042   norm = pow(normtA3, 3.);
01043   for(i=0;i<=N;i++)
01044     dhA3[i]=dtA3[i]/normtA3-tA3[i]*inner/norm;
01045 
01046   free(dtA3);
01047   return 0;
01048 }
01049 
01050 /* calc_function_G */
01051 /* A1,A2,A3 must be orthonormalized */
01052 /* dhA2db=d(A2)/d(beta), d() is pertial derivative */
01053 /* funcG[][][][] :  function G_{ij\alpha\beta} */
01054 
01055 int calc_function_G(/* input */
01056                int N,double *Sn,double fmin,double fmax,
01057                double *A1,double *A2,double *A3,
01058                double *dhA2db,double *dhA3db,
01059                /* output */
01060                double funcG[7][7][4][4])
01061 {
01062   int i,j,k,l,m,imin;
01063   double freq,df,*freq2,sum;
01064   double inn1[7][7][4][4],inn2[7][7][4];
01065 
01066 
01067   /*
01068   dcomplex u[7][4][N+1],A[7][N+1],ctmp;
01069   */
01070   dcomplex *u[7][4],*A[7],ctmp;
01071 
01072   for(i=0;i<=6;i++)
01073   for(j=0;j<=3;j++)
01074   {
01075      u[i][j] = (dcomplex *) malloc(sizeof(dcomplex)*(N+1));
01076   }
01077   for(i=0;i<=6;i++)
01078   {
01079      A[i] = (dcomplex *) malloc(sizeof(dcomplex)*(N+1));
01080   }
01081 
01082   df=(fmax)/N;
01083   imin=fmin/df;
01084   
01085   for(i=0;i<=N;i++){
01086     A[1][i]=DComplex(A1[i],0.);
01087     A[2][i]=DComplex(A2[i],0.);
01088     A[3][i]=DComplex(A3[i],0.);
01089     A[4][i]=DComplex(0.,A1[i]);
01090     A[5][i]=DComplex(0.,A2[i]);
01091     A[6][i]=DComplex(0.,A3[i]);
01092   }
01093  
01094   for(j=1;j<=6;j++){
01095     for(i=0;i<=N;i++){
01096       freq=df*i;
01097       ctmp=DComplex(0.,2*PI*freq/DTRENORM);
01098       u[j][0][i]=DCmul(ctmp,A[j][i]);
01099     }
01100   }
01101 
01102   for(i=0;i<=N;i++){
01103     u[1][3][i]=DComplex(0.,0.);
01104     u[2][3][i]=DComplex(dhA2db[i],0.);
01105     u[3][3][i]=DComplex(dhA3db[i],0.);
01106     u[4][3][i]=DComplex(0.,0.);
01107     u[5][3][i]=DComplex(0.,dhA2db[i]);
01108     u[6][3][i]=DComplex(0.,dhA3db[i]);
01109   }
01110 
01111   freq2 = (double *) malloc(sizeof(double)*(N+1));
01112   freq2[0]=0.;
01113   for(i=1;i<=N;i++){
01114     freq=df*i;
01115     freq2[i]=pow(freq,-5./3.);
01116   }
01117   
01118   for(j=1;j<=6;j++){
01119     for(i=0;i<=N;i++){
01120       ctmp=DComplex(0.,freq2[i]);
01121       u[j][1][i]=DCmul(ctmp,A[j][i]);
01122     }
01123   }
01124 
01125   freq2[0]=0.;
01126   for(i=1;i<=N;i++){
01127     freq=df*i;
01128     freq2[i]=pow(freq,-2./3.);
01129   }
01130   for(j=1;j<=6;j++){
01131     for(i=0;i<=N;i++){
01132       ctmp=DComplex(0.,freq2[i]);
01133       u[j][2][i]=DCmul(ctmp,A[j][i]);
01134     }
01135   }
01136   free(freq2);
01137 
01138   for(i=1;i<=6;i++)
01139     for(j=1;j<=6;j++)
01140       for(k=0;k<=3;k++)
01141         for(l=0;l<=3;l++){
01142           innerC(N,u[i][k],u[j][l],Sn,fmin,fmax,&sum);
01143           inn1[i][j][k][l]=sum;
01144         }
01145 
01146   for(i=1;i<=6;i++)
01147     for(j=1;j<=6;j++)
01148       for(k=0;k<=3;k++){
01149         innerC(N,u[i][k],A[j],Sn,fmin,fmax,&sum);
01150         inn2[i][j][k]=sum;
01151       }
01152 
01153   for(i=1;i<=6;i++)
01154     for(j=1;j<=6;j++)
01155       for(k=0;k<=3;k++)
01156         for(l=0;l<=3;l++){
01157           sum=0;
01158           for(m=1;m<=6;m++)
01159             sum+=inn2[i][m][k]*inn2[j][m][l];
01160 
01161           funcG[i][j][k][l]=inn1[i][j][k][l]-sum;
01162         }
01163 
01164   for(i=0;i<=6;i++)
01165   for(j=0;j<=3;j++)
01166   {
01167      free(u[i][j]);
01168   }
01169   for(i=0;i<=6;i++)
01170   {
01171      free(A[i]);
01172   }
01173 
01174   return 0;
01175 }
01176 
01177 
01178 int orthonormalized_A(/* input */
01179                       int N,double *A1, double *A2,double *A3,double *Sn,
01180                       double fmin,double fmax,
01181                       /* output */
01182                       double *tA2,double *tA3,
01183                       double *hA1,double *hA2, double *hA3,
01184                       double *normtA2,double *normtA3)
01185 {
01186   int i;
01187   double tmp,a,b,d;
01188   double A1A1,A1A2,A1A3,hA2A3;
01189 
01190   innerR(N,A1,A1,Sn,fmin,fmax,&A1A1);
01191   innerR(N,A1,A2,Sn,fmin,fmax,&A1A2);
01192   innerR(N,A1,A3,Sn,fmin,fmax,&A1A3);
01193 
01194   a=sqrt(A1A1);
01195   for(i=0;i<=N;i++)
01196     hA1[i]=A1[i]/a;
01197 
01198   b=A1A2/a;
01199   for(i=0;i<=N;i++){
01200     tA2[i]=A2[i]-b*hA1[i];
01201   }
01202 
01203   innerR(N,tA2,tA2,Sn,fmin,fmax,&tmp);
01204   *normtA2=sqrt(tmp);  
01205 
01206   for(i=0;i<=N;i++)
01207     hA2[i]=tA2[i]/(*normtA2);
01208 
01209   innerR(N,hA2,A3,Sn,fmin,fmax,&hA2A3);
01210 
01211   d=A1A3/a;
01212   for(i=0;i<=N;i++){
01213     tA3[i]=A3[i]-d*hA1[i]-hA2A3*hA2[i];
01214   }
01215 
01216   innerR(N,tA3,tA3,Sn,fmin,fmax,&tmp);
01217   *normtA3=sqrt(tmp);  
01218 
01219   for(i=0;i<=N;i++)
01220     hA3[i]=tA3[i]/(*normtA3);
01221 
01222   return 0;
01223 }
01224 int deriv_A(/* input */
01225             int N,double *costerm,double *sinterm,double fmax,
01226             /* output */
01227             double *dA2,double *dA3)
01228 {
01229   int i;
01230   double df,freq,freq2;
01231 
01232   df=(fmax)/N;
01233 
01234   dA2[0]=0.;dA3[0]=0.;
01235   for(i=1;i<=N;i++){
01236     freq=df*i;
01237     freq2=pow(freq,-11/6.);
01238     dA2[i]=-freq2*sinterm[i];
01239     dA3[i]=freq2*costerm[i];
01240   }
01241   
01242   return 0;
01243 }
01244 int functionG(/* input */
01245               int N,double beta,double *Sn,double fmin,double fmax,
01246               /* output */
01247               double funcG[7][7][4][4])
01248 {
01249   double *A1,*A2,*A3,*tA2,*tA3,*hA1,*hA2,*hA3;
01250   double *costerm,*sinterm;
01251   double *dA2,*dA3,*dhA2,*dhA3;
01252   double normtA2,normtA3;
01253   
01254 
01255   A1 = (double *) malloc(sizeof(double)*(N+1));
01256   A2 = (double *) malloc(sizeof(double)*(N+1));
01257   A3 = (double *) malloc(sizeof(double)*(N+1));
01258   dA2 = (double *) malloc(sizeof(double)*(N+1));
01259   dA3 = (double *) malloc(sizeof(double)*(N+1));
01260   costerm = (double *) malloc(sizeof(double)*(N+1));
01261   sinterm = (double *) malloc(sizeof(double)*(N+1));
01262 
01263   cos_sin_func(N,beta,fmax,costerm,sinterm);
01264   coef_A(N,costerm,sinterm,fmax,A1,A2,A3);
01265   deriv_A(N,costerm,sinterm,fmax,dA2,dA3);
01266 
01267   free(costerm);
01268   free(sinterm);
01269 
01270   tA2 = (double *) malloc(sizeof(double)*(N+1));
01271   tA3 = (double *) malloc(sizeof(double)*(N+1));
01272   hA1 = (double *) malloc(sizeof(double)*(N+1));
01273   hA2 = (double *) malloc(sizeof(double)*(N+1));
01274   hA3 = (double *) malloc(sizeof(double)*(N+1));
01275   dhA2 = (double *) mall