DirectedMeshTest.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Teviet Creighton
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="DirectedMeshTestCV">
00021 Author: Creighton, T. D.
00022 $Id: DirectedMeshTest.c,v 1.2 2007/06/08 14:41:52 bema Exp $
00023 **************************************************** </lalVerbatim> */
00024 
00025 /********************************************************** <lalLaTeX>
00026 
00027 \subsection{Program \texttt{DirectedMeshTest.c}}
00028 \label{ss:DirectedMeshTest.c}
00029 
00030 Computes the sky-position metric for a coherent or semicoherent pulsar
00031 search.
00032 
00033 \subsubsection*{Usage}
00034 \begin{verbatim}
00035 DirectedMeshTest [-o outfile] [-d debuglevel] [-p n dt t0 f0] [-l lat lon]
00036                  [-s ra dec] [-r dra ddec] [-t tau] [-m mismatch]
00037 \end{verbatim}
00038 
00039 \subsubsection*{Description}
00040 
00041 This test program computes template meshes for directed pulsar
00042 searches with spindown, where it is assumed that the parameter metric
00043 is constant over the search space.  The following option flags are
00044 accepted:
00045 \begin{itemize}
00046 \item[\texttt{-o}] Prints the template mesh to the file
00047 \verb@outfile@: each line consists of a sequence of
00048 whitespace-separated numbers representing the coordinates of the
00049 template.  If absent, the routines are exercised, but no output is
00050 written.
00051 \item[\texttt{-d}] Sets the debug level to \verb@debuglevel@; if
00052 absent, \verb@-d 0@ is assumed.
00053 \item[\texttt{-p}] Sets the search parameters: the number of stacks
00054 \verb@n@, the length of each stack \verb@dt@ (in seconds), and the
00055 start time of the first stack \verb@t0@ (in seconds of GPS time), and
00056 the maximum source frequency \verb@f0@ (in Hz).  If absent,
00057 \verb@-t 1 86400 0 1000@ is assumed.
00058 \item[\texttt{-l}] Sets the detector latitude to \verb@lat@ (in
00059 degrees north from the equator) and longitude to \verb@lon@ (in
00060 degrees east of the prime meridian).  If absent,
00061 \verb@-l 52.247 9.822@ (GEO600) is assumed.
00062 \item[\texttt{-s}] Sets the right ascension and declination of the
00063 target to \verb@ra@ and \verb@dec@ degrees, respectively.  If absent,
00064 \verb@-r 192.8594813 27.1282511@ is assumed (the Galactic core).
00065 \item[\texttt{-r}] Sets the range of the sky search to $\pm$\verb@dra@
00066 degrees in right ascension and $\pm$\verb@ddec@ degrees in declination
00067 about the target point.  If absent, \verb@-s 0 0@ is assumed (no
00068 search over sky position).
00069 \item[\texttt{-t}] Sets the range of the spindown search according to
00070 the spindown timescale \verb@tau@, in seconds: the spindown parameter
00071 $f_k$ is constrained by $|f_k|\leq$\verb@tau@${}^{-k}$.  If absent,
00072 \verb@-t 3.16e9@ (century-long spindown) is assumed.
00073 \item[\texttt{-m}] Sets the maximum mismatch threshold of the mesh to
00074 \verb@mismatch@.  If absent, \verb@-m 0.25@ is assumed.
00075 \end{itemize}
00076 
00077 The program automatically determines how many spindown terms are
00078 required to cover the parameter space, by starting with none (or one
00079 if the search is \emph{only} over spindown), computing the local
00080 template density from the parameter metric, and estimating the number
00081 of templates required to cover the search volume.  The number of
00082 spindown parameters is then increased and the number of templates
00083 re-estimated.  Eventually the estimated number of templates will start
00084 to \emph{decrease}, as the proper width of the parameter space in the
00085 new dimensions is less than one template width.  The last dimension
00086 before that happens is the correct dimension to use.
00087 
00088 \subsubsection*{Exit codes}
00089 ****************************************** </lalLaTeX><lalErrTable> */
00090 #define DIRECTEDMESHTESTC_ENORM 0
00091 #define DIRECTEDMESHTESTC_ESUB  1
00092 #define DIRECTEDMESHTESTC_EARG  2
00093 #define DIRECTEDMESHTESTC_EVAL  3
00094 #define DIRECTEDMESHTESTC_EMEM  4
00095 #define DIRECTEDMESHTESTC_EDET  5
00096 #define DIRECTEDMESHTESTC_EFILE 6
00097 
00098 #define DIRECTEDMESHTESTC_MSGENORM "Normal exit"
00099 #define DIRECTEDMESHTESTC_MSGESUB  "Subroutine failed"
00100 #define DIRECTEDMESHTESTC_MSGEARG  "Error parsing arguments"
00101 #define DIRECTEDMESHTESTC_MSGEVAL  "Input argument out of valid range"
00102 #define DIRECTEDMESHTESTC_MSGEMEM  "Memory allocation error"
00103 #define DIRECTEDMESHTESTC_MSGEDET  "Non-positive metric determinant"
00104 #define DIRECTEDMESHTESTC_MSGEFILE "Could not open file"
00105 /******************************************** </lalErrTable><lalLaTeX>
00106 
00107 \subsubsection*{Algorithm}
00108 
00109 The program is fairly straightforward.  It uses
00110 \verb@LALStackMetric()@ to compute the parameter metric, passing it a
00111 canonical time function \verb@LALDTComp()@ that composites the
00112 \verb@LALDTSpin()@ and \verb@LALDTBaryPtolemaic()@ time
00113 transformations.  It starts with a single spindown parameter.  (If a
00114 \emph{search} over sky position is also indicated, it will start with
00115 \emph{no} spindown parameters, using only the barycentric time
00116 transformation rather than the composite transformation.)  The
00117 determinant of the metric is computed, and the number of patches
00118 estimated as:
00119 \begin{equation}
00120 N_\mathrm{patches} \approx \frac{\sqrt{|\mathsf{g}_{ab}|}}
00121         {(\mathrm{mismatch}/n)^{n/2}}
00122         \left\{\Delta\alpha\Delta\delta\right\}
00123         \tau^{-n_s(n_s+1)/2}
00124 \end{equation}
00125 where $\mathsf{g}_{ab}$ is the parameter metric (spindown sector only
00126 if the sky search space is a single point), $n$ is the number of
00127 dimensions in the search, $n_s$ is the number of spindown terms, and
00128 $\Delta\alpha$ and $\Delta\delta$ are the half-ranges of the search in
00129 right ascension and declination, respectively (assuming these ranges
00130 are nonzero).  For the first round we are considering a search
00131 \emph{only} over sky position ($n=2$, $n_s=0$) or a single spindown
00132 search ($n=n_s=1$, ignore the term in braces).  The determinant is
00133 computed using \verb@LALDMatrixDeterminantErr()@, repacking into
00134 \verb@REAL8Array@s the metric components and uncertainties returned by
00135 \verb@LALStackMetric()@.  An error is generated if the determinant is
00136 non-positive, or a warning if it is smaller than its estimated
00137 uncertainty.
00138 
00139 In subsequent trials, we increase $n_s$ successivlely by 1, and
00140 recompute $\mathsf{g}_{ab}$ and $N_\mathrm{patches}$.  Eventually,
00141 when the width of the added dimension is less than one patch witdh,
00142 $N_\mathrm{patches}$ will decrease.  When this happend, we back up to
00143 the value of $n_s$ that gave the largest number of patches, and use
00144 that parameter metric.
00145 
00146 The program then uses \verb@LALDSymmetricEigenVectors()@ to compute
00147 the eigenvalues and eigenvectors of the metric; these are combined and
00148 repacked into a \verb@REAL4VectorSequence@ used by
00149 \verb@LALFlatMesh()@, as described in \verb@FlatMesh.h@.  The inverse
00150 transformation is computed using \verb@LALDMatrixInverse()@, and again
00151 repacked into a \verb@REAL4VectorSequence@.  The search area is taken
00152 to be a rectangular space controled by \verb@LALRectIntersect()@,
00153 covering the sky area $|\alpha-\mathtt{ra}|\leq\mathtt{dra}$ and
00154 $|\alpha-\mathtt{ra}|\leq\mathtt{dra}$ (provided these ranges are
00155 nonzero), and the spindown volume $|f_k|\leq\mathtt{tau}^{-k}$ for
00156 $k=1,\ldots,n_s$.  The volume boundaries are increased by half the
00157 maximum patch size in each direction, to ensure total coverage of the
00158 edges, as described in \verb@FlatMeshTest.c@.
00159 
00160 \subsubsection*{Uses}
00161 \begin{verbatim}
00162 lalDebugLevel
00163 LALPrintError()                 LALCheckMemoryLeaks()
00164 LALCalloc()                     LALFree()
00165 LALU4CreateVector()             LALU4DestroyVector()
00166 LALSCreateVector()              LALSDestroyVector()
00167 LALDCreateVector()              LALDDestroyVector()
00168 LALSCreateVectorSequence()      LALSDestroyVectorSequence()
00169 LALDCreateArray()               LALDDestroyArray()
00170 LALDTBaryPtolemaic()            LALTBaryPtolemaic()
00171 LALDTSpin()                     LALTSpin()
00172 LALDTComp()                     LALGetEarthTimes()
00173 LALCreateFlatMesh()             LALRectIntersect()
00174 LALStackMetric()                LALProjectMetric()
00175 LALDMatrixDeterminantErr()      LALDMatrixInverse()
00176 LALDSymmetricEigenVectors()     LALSnprintf()
00177 \end{verbatim}
00178 
00179 \subsubsection*{Notes}
00180 
00181 \vfill{\footnotesize\input{DirectedMeshTestCV}}
00182 
00183 ******************************************************* </lalLaTeX> */
00184 
00185 #include <math.h>
00186 #include <stdlib.h>
00187 #include <lal/LALStdlib.h>
00188 #include <lal/LALStdio.h>
00189 #include <lal/LALConstants.h>
00190 #include <lal/AVFactories.h>
00191 #include <lal/SeqFactories.h>
00192 #include <lal/MatrixUtils.h>
00193 #include <lal/StackMetric.h>
00194 #include <lal/PulsarTimes.h>
00195 #include <lal/FlatMesh.h>
00196 
00197 NRCSID( DIRECTEDMESHTESTC, "$Id: DirectedMeshTest.c,v 1.2 2007/06/08 14:41:52 bema Exp $" );
00198 
00199 /* Default parameter settings. */
00200 int lalDebugLevel = 0;
00201 #define NSTACKS 1
00202 #define STACKLENGTH 86400.0 /* arbitrary */
00203 #define STARTTIME 0.0       /* arbitrary */
00204 #define LATITUDE  52.247    /* GEO600 location */
00205 #define LONGITUDE 9.822     /* GEO600 location */
00206 #define FREQUENCY 1000.0    /* arbitrary */
00207 #define RA 192.8594813      /* Galactic core */
00208 #define DEC 27.1282511      /* Galactic core */
00209 #define TAU 3.16e9          /* century-scale spindown */
00210 #define MISMATCH 0.25       /* arbitrary but reasonably optimal */
00211 
00212 /* Usage format string. */
00213 #define USAGE "Usage: %s [-o outfile] [-d debuglevel] [-p n dt t0 f0]\n" \
00214 "\t[-l lat lon] [-s ra dec] [-r dra ddec] [-t tau] [-m mismatch]\n"
00215 
00216 /* Input error checking: Some accepted parameter ranges. */
00217 #define NMAX  10000 /* 1 <= number of stacks <= NMAX */
00218 #define DTMAX  3e10 /* 1/f_0 < stack length <= DTMAX */
00219 #define F0MAX  1e4  /* 0 < f_0 <= FOMAX */
00220 /* Also: |latitude| and |dec| will be restricted to <= 90 degrees,
00221          |longitude| and |ra| will be restricted to <= 360 degrees */
00222 
00223 /* Other internal constants. */
00224 #define MAXLEN 1024 /* maximum format or warning message length */
00225 
00226 
00227 /* Macros for printing errors and testing subroutines. */
00228 #define ERROR( code, msg, statement )                                \
00229 do                                                                   \
00230 if ( lalDebugLevel & LALERROR )                                      \
00231 {                                                                    \
00232   LALPrintError( "Error[0] %d: program %s, file %s, line %d, %s\n"   \
00233                  "        %s %s\n", (code), *argv, __FILE__,         \
00234                  __LINE__, DIRECTEDMESHTESTC, statement ? statement :\
00235                  "", (msg) );                                        \
00236 }                                                                    \
00237 while (0)
00238 
00239 #define WARNING( statement )                                         \
00240 do                                                                   \
00241 if ( lalDebugLevel & LALWARNING )                                    \
00242 {                                                                    \
00243   LALPrintError( "Warning[0]: program %s, file %s, line %d, %s\n"    \
00244                  "        %s\n", *argv, __FILE__, __LINE__,          \
00245                  DIRECTEDMESHTESTC, (statement) );                   \
00246 }                                                                    \
00247 while (0)
00248 
00249 #define INFO( statement )                                            \
00250 do                                                                   \
00251 if ( lalDebugLevel & LALINFO )                                       \
00252 {                                                                    \
00253   LALPrintError( "Info[0]: program %s, file %s, line %d, %s\n"       \
00254                  "        %s\n", *argv, __FILE__, __LINE__,          \
00255                  DIRECTEDMESHTESTC, (statement) );                   \
00256 }                                                                    \
00257 while (0)
00258 
00259 #define SUB( func, statusptr )                                       \
00260 do                                                                   \
00261 if ( (func), (statusptr)->statusCode )                               \
00262 {                                                                    \
00263   ERROR( DIRECTEDMESHTESTC_ESUB, DIRECTEDMESHTESTC_MSGESUB,          \
00264          "Function call \"" #func "\" failed:" );                    \
00265   return DIRECTEDMESHTESTC_ESUB;                                     \
00266 }                                                                    \
00267 while (0)
00268 
00269 #define CHECKVAL( val, lower, upper )                                \
00270 do                                                                   \
00271 if ( ( (val) <= (lower) ) || ( (val) > (upper) ) )                   \
00272 {                                                                    \
00273   ERROR( DIRECTEDMESHTESTC_EVAL, DIRECTEDMESHTESTC_MSGESUB,          \
00274          "Value of " #val " out of range:" );                        \
00275   LALPrintError( #val " = %f, range = (%f,%f]\n", (REAL8)(val),      \
00276                  (REAL8)(lower), (REAL8)(upper) );                   \
00277   return DIRECTEDMESHTESTC_EVAL;                                     \
00278 }                                                                    \
00279 while (0)
00280 
00281 /* A global pointer for debugging. */
00282 #ifndef NDEBUG
00283 char *lalWatch;
00284 #endif
00285 
00286 /* Prototype for a routine to print floating-point numbers with
00287    uncertainties. */
00288 int
00289 fprintderr( FILE *fp, REAL8 x, REAL8 dx );
00290 
00291 int
00292 main(int argc, char **argv)
00293 {
00294   /* Variables for parsing command-line arguments. */
00295   INT4  arg;                   /* argument list counter */
00296   CHAR *outfile = NULL;        /* output filename */
00297   UINT4 n = NSTACKS;           /* number of stacks or dimensions */
00298   REAL8 dt = STACKLENGTH;      /* length of each stack (s) */
00299   REAL8 t0 = STARTTIME;        /* start time of first stack (GPS s) */
00300   REAL8 f0 = FREQUENCY;        /* maximum frequency of search */
00301   REAL8 lat = LATITUDE;        /* latitude of detector (degrees N) */
00302   REAL8 lon = LONGITUDE;       /* longitude of detector (degrees E) */
00303   REAL8 ra = RA, dec = DEC;    /* sky position (degrees) */
00304   REAL8 dra = 0.0, ddec = 0.0; /* sky position range (degrees) */
00305   REAL8 tau = TAU;             /* spindown timescale (s) */
00306   REAL8 mismatch = MISMATCH;   /* maximum mismatch threshold */
00307 
00308   /* Other variables. */
00309   UINT4 i, j, ij, ji;           /* indecies */
00310   UINT4 nSpin, nSky;            /* dimensions of search */
00311   UINT4 err = 1;                /* 1 if no errors, 2 if errors. */
00312   REAL8Vector *lambda = NULL;   /* parameter/eigenvalue vector */
00313   REAL8Vector *metric = NULL;   /* current metric as a REAL8Vector */
00314   REAL8Array *current = NULL;   /* current metric as a REAL8Array */
00315   REAL8Array *dMatrix = NULL;   /* current metric uncertainties */
00316   REAL8Array *previous = NULL;  /* previous metric as a REAL8Array */
00317   REAL8 *mData, *cData, *dData; /* (metric, current, dMatrix)->data */
00318   REAL4 *sData, *width;         /* data pointers for edge calculations */
00319   REAL8 det[2];                 /* metric determinant and uncertainty */
00320   REAL8 vol, np;                /* variables for volumes, patch numbers */
00321   UINT4Vector dimLength;        /* structure to create arrays */
00322   UINT4 dimData[2];             /* dimLength.data storage */
00323   CreateVectorSequenceIn in;    /* structure to create vector sequence */
00324   REAL4VectorSequence *mesh = NULL; /* template list */
00325   static LALStatus stat;            /* top-level status structure */
00326   static LIGOTimeGPS start;         /* GPS start time of first stack */
00327   static MetricParamStruc params;   /* metric computation parameters */
00328   static FlatMeshParamStruc meshParams; /* mesh creation parameters */
00329   static PulsarTimesParamStruc baryParams; /* barycentring parameters */
00330   static PulsarTimesParamStruc spinParams; /* spindown parameters */
00331   static PulsarTimesParamStruc compParams; /* composite parameters */
00332 
00333   /* Set up array creation structure. */
00334   dimLength.length = 2;
00335   dimLength.data = dimData;
00336 
00337   /******************************************************************
00338    * ARGUMENT PARSING                                               *
00339    ******************************************************************/
00340 
00341   /* Parse argument list.  arg stores the current position. */
00342   arg = 1;
00343   while ( arg < argc ) {
00344     /* Parse output file option. */
00345     if ( !strcmp( argv[arg], "-o" ) ) {
00346       if ( argc > arg + 1 ) {
00347         arg++;
00348         outfile = argv[arg++];
00349       } else {
00350         ERROR( DIRECTEDMESHTESTC_EARG, DIRECTEDMESHTESTC_MSGEARG, 0 );
00351         LALPrintError( USAGE, *argv );
00352         return DIRECTEDMESHTESTC_EARG;
00353       }
00354     }
00355     /* Parse search parameter option. */
00356     else if ( !strcmp( argv[arg], "-p" ) ) {
00357       if ( argc > arg + 4 ) {
00358         arg++;
00359         n = atoi( argv[arg++] );
00360         dt = atof( argv[arg++] );
00361         t0 = atof( argv[arg++] );
00362         f0 = atof( argv[arg++] );
00363       } else {
00364         ERROR( DIRECTEDMESHTESTC_EARG, DIRECTEDMESHTESTC_MSGEARG, 0 );
00365         LALPrintError( USAGE, *argv );
00366         return DIRECTEDMESHTESTC_EARG;
00367       }
00368     }
00369     /* Parse detector position option. */
00370     else if ( !strcmp( argv[arg], "-l" ) ) {
00371       if ( argc > arg + 2 ) {
00372         arg++;
00373         lat = atof( argv[arg++] );
00374         lon = atof( argv[arg++] );
00375       } else {
00376         ERROR( DIRECTEDMESHTESTC_EARG, DIRECTEDMESHTESTC_MSGEARG, 0 );
00377         LALPrintError( USAGE, *argv );
00378         return DIRECTEDMESHTESTC_EARG;
00379       }
00380     }
00381     /* Parse sky position option. */
00382     else if ( !strcmp( argv[arg], "-s" ) ) {
00383       if ( argc > arg + 2 ) {
00384         arg++;
00385         ra = atof( argv[arg++] );
00386         dec = atof( argv[arg++] );
00387       } else {
00388         ERROR( DIRECTEDMESHTESTC_EARG, DIRECTEDMESHTESTC_MSGEARG, 0 );
00389         LALPrintError( USAGE, *argv );
00390         return DIRECTEDMESHTESTC_EARG;
00391       }
00392     }
00393     /* Parse sky range option. */
00394     else if ( !strcmp( argv[arg], "-r" ) ) {
00395       if ( argc > arg + 2 ) {
00396         arg++;
00397         dra = atof( argv[arg++] );
00398         ddec = atof( argv[arg++] );
00399       } else {
00400         ERROR( DIRECTEDMESHTESTC_EARG, DIRECTEDMESHTESTC_MSGEARG, 0 );
00401         LALPrintError( USAGE, *argv );
00402         return DIRECTEDMESHTESTC_EARG;
00403       }
00404     }
00405     /* Parse spindown timescale option. */
00406     else if ( !strcmp( argv[arg], "-t" ) ) {
00407       if ( argc > arg + 1 ) {
00408         arg++;
00409         tau = atof( argv[arg++] );
00410       } else {
00411         ERROR( DIRECTEDMESHTESTC_EARG, DIRECTEDMESHTESTC_MSGEARG, 0 );
00412         LALPrintError( USAGE, *argv );
00413         return DIRECTEDMESHTESTC_EARG;
00414       }
00415     }
00416     /* Parse debug level option. */
00417     else if ( !strcmp( argv[arg], "-d" ) ) {
00418       if ( argc > arg + 1 ) {
00419         arg++;
00420         lalDebugLevel = atoi( argv[arg++] );
00421       } else {
00422         ERROR( DIRECTEDMESHTESTC_EARG, DIRECTEDMESHTESTC_MSGEARG, 0 );
00423         LALPrintError( USAGE, *argv );
00424         return DIRECTEDMESHTESTC_EARG;
00425       }
00426     }
00427     /* Check for unrecognized options. */
00428     else {
00429       ERROR( DIRECTEDMESHTESTC_EARG, DIRECTEDMESHTESTC_MSGEARG, 0 );
00430       LALPrintError( USAGE, *argv );
00431       return DIRECTEDMESHTESTC_EARG;
00432     }
00433   } /* End of argument parsing loop. */
00434 
00435   /* Do error trapping on input parameters. */
00436   if ( lalDebugLevel & LALERROR ) {
00437     CHECKVAL( n, 0, NMAX );
00438     CHECKVAL( f0, 0.0, F0MAX );
00439     CHECKVAL( dt, 1.0/f0, DTMAX );
00440     CHECKVAL( lat, -90.0, 90.0 );
00441     CHECKVAL( lon, -360.0, 360.0 );
00442     CHECKVAL( dec, -90.0, 90.0 );
00443     CHECKVAL( ra, -360.0, 360.0 );
00444     CHECKVAL( tau, 0.0, LAL_REAL8_MAX );
00445   }
00446   if ( tau < n*dt )
00447     WARNING( "Spindown timescale less than observation time!" );
00448 
00449   /* Convert degrees to radians. */
00450   lat *= LAL_PI_180;
00451   lon *= LAL_PI_180;
00452   ra *= LAL_PI_180;
00453   dec *= LAL_PI_180;
00454   dra *= LAL_PI_180;
00455   ddec *= LAL_PI_180;
00456 
00457   /******************************************************************
00458    * METRIC COMPUTATION                                             *
00459    ******************************************************************/
00460 
00461   /* Set up start time. */
00462   start.gpsSeconds = (INT4)t0;
00463   start.gpsNanoSeconds = (INT4)( 1.0e9*( t0 - start.gpsSeconds ) );
00464   t0 = 0.0;
00465 
00466   /* Set up constant parameters for barycentre transformation. */
00467   baryParams.epoch = start;
00468   baryParams.latitude = lat;
00469   baryParams.longitude = lon;
00470   SUB( LALGetEarthTimes( &stat, &baryParams ), &stat );
00471 
00472   /* Set up constant parameters for spindown transformation. */
00473   spinParams.epoch = start;
00474   spinParams.t0 = t0;
00475 
00476   /* Set up constant parameters for composed transformation. */
00477   compParams.epoch = start;
00478   compParams.t1 = LALTBaryPtolemaic;
00479   compParams.t2 = LALTSpin;
00480   compParams.dt1 = LALDTBaryPtolemaic;
00481   compParams.dt2 = LALDTSpin;
00482   compParams.constants1 = &baryParams;
00483   compParams.constants2 = &spinParams;
00484   compParams.nArgs = 2;
00485 
00486   /* Set up constant parameters for initial metric calculation. */
00487   if ( dra == 0.0 || ddec == 0.0 ) {
00488     params.dtCanon = LALDTComp;
00489     params.constants = &compParams;
00490     nSpin = 1;
00491     nSky = 0;
00492   } else {
00493     params.dtCanon = LALDTBaryPtolemaic;
00494     params.constants = &baryParams;
00495     nSpin = 0;
00496     nSky = 2;
00497   }
00498   params.start = t0;
00499   params.deltaT = dt;
00500   params.n = n;
00501   params.errors = 1;
00502   err = 2;
00503 
00504   /* Set up the initial metric and parameter vectors. */
00505   n = nSpin + 3;
00506   SUB( LALDCreateVector( &stat, &metric, err*n*(n+1)/2 ), &stat );
00507   mData = metric->data;
00508   SUB( LALDCreateVector( &stat, &lambda, n ), &stat );
00509   lambda->data[0] = f0;
00510   lambda->data[1] = ra;
00511   lambda->data[2] = dec;
00512   if ( nSpin )
00513     memset( lambda->data + 3, 0, nSpin*sizeof(REAL8) );
00514 
00515   /* Compute the initial metric and its projection. */
00516   SUB( LALStackMetric( &stat, metric, lambda, &params ), &stat );
00517   SUB( LALDDestroyVector( &stat, &lambda ), &stat );
00518   SUB( LALProjectMetric( &stat, metric, params.errors ), &stat );
00519 
00520   /* Copy appropriate metric components into a matrx. */
00521   dimData[0] = dimData[1] = n = nSpin + nSky;
00522   SUB( LALDCreateArray( &stat, &current, &dimLength ), &stat );
00523   cData = current->data;
00524   for ( i = 0; i < n; i++ ) {
00525     cData[i*(n+1)] = mData[err*(i+3-nSky)*(i+6-nSky)/2];
00526     for ( j = 0; j < i; j++ )
00527       cData[i*n+j] = cData[j*n+i]
00528         = mData[err*(j+3-nSky) + err*(i+3-nSky)*(i+4-nSky)/2];
00529   }
00530   if ( params.errors ) {
00531     SUB( LALDCreateArray( &stat, &dMatrix, &dimLength ), &stat );
00532     dData = dMatrix->data;
00533     for ( i = 0; i < n; i++ ) {
00534       dData[i*(n+1)] = mData[err*(i+3-nSky)*(i+6-nSky)/2 + 1];
00535       for ( j = 0; j < i; j++ )
00536         dData[i*n+j] = dData[j*n+i]
00537           = mData[err*(j+3-nSky) + err*(i+3-nSky)*(i+4-nSky)/2 + 1];
00538     }
00539   }
00540   SUB( LALDDestroyVector( &stat, &metric ), &stat );
00541 
00542 
00543   for ( i = 0; i < n; i++ ) {
00544     fprintf( stderr, "%25.16e", cData[i*n] );
00545     for ( j = 1; j < n; j++ )
00546       fprintf( stderr, "% 25.16e", cData[i*n+j] );
00547     fprintf( stderr, "\n" );
00548   }
00549 
00550 
00551 
00552   /* Estimate the number of templates required. */
00553   SUB( LALDMatrixDeterminantErr( &stat, det, current, dMatrix ),
00554        &stat );
00555   if ( params.errors ) {
00556     SUB( LALDDestroyArray( &stat, &dMatrix ), &stat );
00557   }
00558   if ( det[0] <= 0.0 ) {
00559     ERROR( DIRECTEDMESHTESTC_EDET, DIRECTEDMESHTESTC_MSGEDET, 0 );
00560     return DIRECTEDMESHTESTC_EDET;
00561   }
00562   if ( det[0] <= det[1] )
00563     WARNING( "Uncertainty in determinant greater than value" );
00564   det[0] = sqrt( det[0] );
00565   det[1] /= 2.0*det[0];
00566   vol = pow( mismatch/( (REAL8)( n ) ), 0.5*( (REAL8)( n ) ) );
00567   vol *= pow( tau, -0.5*( (REAL8)( nSpin*( nSpin + 1 ) ) ) );
00568   if ( nSky )
00569     vol *= dra*ddec;
00570   det[0] *= vol;
00571   det[1] *= vol;
00572   fprintf( stdout, "Estimated number of templates:\n" );
00573   fprintf( stdout, "%i spindown: number of templates = ", nSpin );
00574   fprintderr( stdout, det[0], det[1] );
00575   fprintf( stdout, "\n" );
00576 
00577   /* Increase number of spindown terms, and re-estimate number of
00578      templates. */
00579   params.dtCanon = LALDTComp;
00580   params.constants = &compParams;
00581   do {
00582     nSpin++;
00583 
00584     /* Store old results. */
00585     np = det[0];
00586     if ( previous ) {
00587       SUB( LALDDestroyArray( &stat, &previous ), &stat );
00588     }
00589     previous = current;
00590     current = NULL;
00591 
00592     /* Set up the current metric and parameter vectors. */
00593     n = nSpin + 3;
00594     SUB( LALDCreateVector( &stat, &metric, err*n*(n+1)/2 ), &stat );
00595     mData = metric->data;
00596     SUB( LALDCreateVector( &stat, &lambda, n ), &stat );
00597     lambda->data[0] = f0;
00598     lambda->data[1] = ra;
00599     lambda->data[2] = dec;
00600     memset( lambda->data + 3, 0, nSpin*sizeof(REAL8) );
00601 
00602     /* Compute the current metric and its projection. */
00603     SUB( LALStackMetric( &stat, metric, lambda, &params ), &stat );
00604     SUB( LALDDestroyVector( &stat, &lambda ), &stat );
00605     SUB( LALProjectMetric( &stat, metric, params.errors ), &stat );
00606 
00607     for ( i = 0; i < metric->length/2; i++ )
00608       fprintf( stderr, "%25.16e\n", metric->data[2*i] );
00609 
00610 
00611     /* Copy appropriate metric components into a matrx. */
00612     dimData[0] = dimData[1] = n = nSpin + nSky;
00613     SUB( LALDCreateArray( &stat, &current, &dimLength ), &stat );
00614     cData = current->data;
00615     for ( i = 0; i < n; i++ ) {
00616       cData[i*(n+1)] = mData[err*(i+3-nSky)*(i+6-nSky)/2];
00617       for ( j = 0; j < i; j++ )
00618         cData[i*n+j] = cData[j*n+i]
00619           = mData[err*(j+3-nSky) + err*(i+3-nSky)*(i+4-nSky)/2];
00620     }
00621     if ( params.errors ) {
00622       SUB( LALDCreateArray( &stat, &dMatrix, &dimLength ), &stat );
00623       dData = dMatrix->data;
00624       for ( i = 0; i < n; i++ ) {
00625         dData[i*(n+1)] = mData[err*(i+3-nSky)*(i+6-nSky)/2 + 1];
00626         for ( j = 0; j < i; j++ )
00627           dData[i*n+j] = dData[j*n+i]
00628             = mData[err*(j+3-nSky) + err*(i+3-nSky)*(i+4-nSky)/2 + 1];
00629       }
00630     }
00631     SUB( LALDDestroyVector( &stat, &metric ), &stat );
00632 
00633 
00634     fprintf( stderr, "\n" );
00635     for ( i = 0; i < n; i++ ) {
00636       fprintf( stderr, "%25.16e", cData[i*n] );
00637       for ( j = 1; j < n; j++ )
00638         fprintf( stderr, "% 25.16e", cData[i*n+j] );
00639       fprintf( stderr, "\n" );
00640     }
00641 
00642 
00643 
00644     /* Estimate the number of templates required. */
00645     SUB( LALDMatrixDeterminantErr( &stat, det, current, dMatrix ),
00646          &stat );
00647     if ( params.errors ) {
00648       SUB( LALDDestroyArray( &stat, &dMatrix ), &stat );
00649     }
00650     if ( det[0] <= 0.0 ) {
00651       ERROR( DIRECTEDMESHTESTC_EDET, DIRECTEDMESHTESTC_MSGEDET, 0 );
00652       return DIRECTEDMESHTESTC_EDET;
00653     }
00654     if ( det[0] <= det[1] )
00655       WARNING( "Uncertainty in determinant greater than value" );
00656     det[0] = sqrt( det[0] );
00657     det[1] /= 2.0*det[0];
00658     vol = pow( mismatch/( (REAL8)( n ) ), 0.5*( (REAL8)( n ) ) );
00659     vol *= pow( tau, -0.5*( (REAL8)( nSpin*( nSpin + 1 ) ) ) );
00660     if ( nSky )
00661       vol *= dra*ddec;
00662     det[0] *= vol;
00663     det[1] *= vol;
00664     fprintf( stdout, "%i spindown: number of templates = ", nSpin );
00665     fprintderr( stdout, det[0], det[1] );
00666     fprintf( stdout, "\n" );
00667   } while ( det[0] > np );
00668 
00669   /******************************************************************
00670    * MESH PLACEMENT                                                 *
00671    ******************************************************************/
00672 
00673   /* Use next-to-last number of spindown terms. */
00674   nSpin--;
00675   dimData[0] = dimData[1] = n = nSpin + nSky;
00676   SUB( LALDDestroyArray( &stat, &current ), &stat );
00677   SUB( LALDCreateArray( &stat, &current, &dimLength ), &stat );
00678   SUB( LALDCreateArray( &stat, &dMatrix, &dimLength ), &stat );
00679   SUB( LALDCreateVector( &stat, &lambda, n ), &stat );
00680 
00681   /* Compute transformation matrices: current stores transformation
00682      matrix, dMatrix stores its inverse, previous gets mangled. */
00683   SUB( LALDSymmetricEigenVectors( &stat, lambda, previous ), &stat );
00684   memcpy( current->data, previous->data, n*n*sizeof(REAL8) );
00685   for ( i = 0; i < n; i++ ) {
00686     REAL8 factor = 2.0*mismatch*sqrt( n*lambda->data[i] );
00687     for ( j = 0, ji = j; j < n; j++, ji += n )
00688       current->data[ji] *= factor;
00689   }
00690   SUB( LALDDestroyVector( &stat, &lambda ), &stat );
00691   SUB( LALDMatrixInverse( &stat, det, previous, dMatrix ), &stat );
00692   SUB( LALDDestroyArray( &stat, &previous ), &stat );
00693 
00694   /* Create flat mesh parameter structure fields. */
00695   in.length = in.vectorLength = n;
00696   SUB( LALSCreateVectorSequence( &stat, &(meshParams.matrix), &in ),
00697        &stat );
00698   SUB( LALSCreateVectorSequence( &stat, &(meshParams.matrixInv),
00699                                  &in ), &stat );
00700   SUB( LALSCreateVector( &stat, &(meshParams.xMax), n ), &stat );
00701   SUB( LALSCreateVector( &stat, &(meshParams.xMin), n ), &stat );
00702   in.length = 2;
00703   SUB( LALSCreateVectorSequence( &stat, &(meshParams.controlPoints),
00704                                  &in ), &stat );
00705 
00706   /* Transpose matrices to agree with convention in FlatMesh.h. */
00707   for ( i = 0; i < n; i++ )
00708     for ( j = 0, ij = i*n, ji = j; j < n; j++, ij++, ji += n ) {
00709       meshParams.matrix->data[ij] = current->data[ji];
00710       meshParams.matrixInv->data[ij] = dMatrix->data[ji];
00711     }
00712   SUB( LALDDestroyArray( &stat, &current ), &stat );
00713   SUB( LALDDestroyArray( &stat, &dMatrix ), &stat );
00714 
00715   /* Set up boundaries. */
00716   sData = meshParams.controlPoints->data;
00717   if ( nSky ) {
00718     sData[0] = ra - dra;
00719     sData[n] = ra + dra;
00720     sData[1] = dec - ddec;
00721     sData[n+1] = dec + ddec;
00722   }
00723   vol = 1.0;
00724   for ( i = nSky; i < n; i++ ) {
00725     sData[i] = -( vol /= tau );
00726     sData[n+i] = vol;
00727   }
00728 
00729   /* Expand boundaries to ensure edge coverage. */
00730   width = (REAL4 *)LALCalloc( n, sizeof(REAL4) );
00731   if ( !width ) {
00732     ERROR( DIRECTEDMESHTESTC_EMEM, DIRECTEDMESHTESTC_MSGEMEM, 0 );
00733     return DIRECTEDMESHTESTC_EMEM;
00734   }
00735   for ( sData = meshParams.matrix->data, i = 0; i < n; i++ )
00736     for ( j = 0; j < n; j++, sData++ )
00737       width[j] += fabs( *sData );
00738   for ( sData = meshParams.controlPoints->data, i = 0; i < n;
00739         i++, sData++ ) {
00740     INT2 direct = ( sData[0] < sData[n] ) ? -1 : 1;
00741     sData[0] += 0.5*direct*width[i];
00742     sData[n] -= 0.5*direct*width[i];
00743   }
00744   LALFree( width );
00745 
00746   /* Copy final boundaries into mesh parameters. */
00747   memcpy( meshParams.xMin->data, meshParams.controlPoints->data,
00748           n*sizeof(REAL4) );
00749   memcpy( meshParams.xMax->data, meshParams.controlPoints->data + n,
00750           n*sizeof(REAL4) );
00751 
00752   /* Compute the mesh, and then clean up memory. */
00753   SUB( LALCreateFlatMesh( &stat, &mesh, &meshParams ), &stat );
00754   SUB( LALSDestroyVector( &stat, &(meshParams.xMax) ), &stat );
00755   SUB( LALSDestroyVector( &stat, &(meshParams.xMin) ), &stat );
00756   SUB( LALSDestroyVectorSequence( &stat, &(meshParams.matrix) ),
00757        &stat );
00758   SUB( LALSDestroyVectorSequence( &stat, &(meshParams.matrixInv) ),
00759        &stat );
00760   SUB( LALSDestroyVectorSequence( &stat, &(meshParams.controlPoints) ),
00761        &stat );
00762 
00763   /* Write output if requested. */
00764   if ( outfile ) {
00765     FILE *fp = fopen( outfile, "w" );
00766     if ( !fp ) {
00767       ERROR( DIRECTEDMESHTESTC_EFILE, "- " DIRECTEDMESHTESTC_MSGEFILE,
00768              outfile );
00769       return DIRECTEDMESHTESTC_EFILE;
00770     }
00771     sData = mesh->data;
00772     i = mesh->length;
00773     while ( i-- ) {
00774       fprintf( fp, "%16.9e", *(sData++) );
00775       for ( j = 1; j < n; j++ )
00776         fprintf( fp, " %16.9e", *(sData++) );
00777       fprintf( fp, "\n" );
00778     }
00779     fclose( fp );
00780   }
00781 
00782   /* Done. */
00783   SUB( LALSDestroyVectorSequence( &stat, &mesh ), &stat );
00784   LALCheckMemoryLeaks();
00785   INFO( DIRECTEDMESHTESTC_MSGENORM );
00786   return DIRECTEDMESHTESTC_ENORM;
00787 }
00788 
00789 
00790 int
00791 fprintderr( FILE *fp, REAL8 x, REAL8 dx ) {
00792   CHAR format[MAXLEN]; /* format string for fprintf() */
00793   INT4 gsd = 0;        /* place index of greatest significant digit */
00794   INT4 lsd = 0;        /* place index of least significant digit */
00795   REAL8 norm;          /* normalization factor */
00796 
00797   /* Compute gsd, lsd, y, and dy. */
00798   if ( dx < LAL_REAL8_EPS*fabs( x ) )
00799     dx = 0.0;
00800   if ( dx > 0.0 ) {
00801     REAL8 lsdd = log( 0.5*dx )/log( 10.0 );
00802     if ( lsdd >= 0.0 )
00803       lsd = (INT4)( lsdd );
00804     else
00805       lsd = (INT4)( lsdd ) - 1;
00806   }
00807   if ( x != 0.0 ) {
00808     REAL8 gsdd = log( fabs( x ) )/log( 10.0 );
00809     if ( gsdd >= 0.0 )
00810       gsd = (INT4)( gsdd );
00811     else
00812       gsd = (INT4)( gsdd ) - 1;
00813   }
00814 
00815   /* If x is zero, format is determined entirely by dx. */
00816   if ( x == 0.0 ) {
00817     if ( dx <= 0.0 )
00818       return fprintf( fp, "0" );
00819     if ( abs( lsd ) > 3 ) {
00820       norm = pow( 10.0, -lsd );
00821       return fprintf( fp, "( 0 +/- %.0f )e%+i", dx*norm, lsd );
00822     }
00823     if ( lsd <= 0 ) {
00824       LALSnprintf( format, MAXLEN, "%%.%if +/- %%.%if", -lsd, -lsd );
00825       return fprintf( fp, format, 0.0, dx );
00826     }
00827     norm = pow( 10.0, -lsd );
00828     LALSnprintf( format, MAXLEN, "0 +/- %%.0f%%0%ii", lsd );
00829     return fprintf( fp, format, dx*norm, 0 );
00830   }
00831 
00832   /* If number is exact to 8-byte precision, print it as such. */
00833   if ( dx <= 0.0 ) {
00834     if ( abs( gsd ) > 3 )
00835       return fprintf( fp, "%.16e", x );
00836     LALSnprintf( format, MAXLEN, "%%.%if", 16 - gsd );
00837     return fprintf( fp, format, x );
00838   }
00839 
00840   /* Otherwise, format depends on x and dx. */
00841   if ( gsd < lsd )
00842     gsd = lsd;
00843   if ( lsd > 3 || gsd < -3 ) {
00844     norm = pow( 10.0, -gsd );
00845     LALSnprintf( format, MAXLEN, "( %%.%if +/- %%.%if )e%+i",
00846                  gsd - lsd, gsd - lsd, gsd );
00847     return fprintf( fp, format, x*norm, dx*norm );
00848   }
00849   if ( lsd <= 0 ) {
00850     LALSnprintf( format, MAXLEN, "%%.%if +/- %%.%if", -lsd, -lsd );
00851     return fprintf( fp, format, x, dx );
00852   }
00853   norm = pow( 10.0, -lsd );
00854   LALSnprintf( format, MAXLEN, "%%.0f%%0%ii +/- %%.0f%%0%ii", lsd,
00855                lsd );
00856   return fprintf( fp, format, x*norm, 0, dx*norm, 0 );
00857 }

Generated on Sat Sep 6 03:06:49 2008 for LAL by  doxygen 1.5.2