Ring.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Duncan Brown, Jolien 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="RingCV">
00021  * Author: Jolien Creighton
00022  * $Id: Ring.c,v 1.13 2008/08/21 14:23:52 lgoggin Exp $
00023  **** </lalVerbatim> */
00024 
00025 #include <math.h>
00026 #include <lal/LALStdlib.h>
00027 #include <lal/LALConstants.h>
00028 #include <lal/LIGOMetadataTables.h>
00029 #include <lal/Ring.h>
00030 
00031 /**** <lalLaTeX>
00032  *
00033  * \subsection{Module \texttt{Ring.c}}
00034  *
00035  * Routines to generate ringdown waveforms and to make a ringdown template bank.
00036  *
00037  * \subsubsection*{Prototypes}
00038  * \input{RingCP}
00039  * \idx{XLALComputeRingTemplate()}
00040  * \idx{XLALComputeBlackHoleRing()}
00041  * \idx{XLALCreateRingTemplateBank()}
00042  * \idx{XLALDestroyRingTemplateBank()}
00043  * 
00044  * \subsubsection*{Description}
00045  * 
00046  * The routine \verb+LALComputeRingTemplate()+ computes the ringdown waveform
00047  * \begin{equation}
00048  *   r(t) = \left\{
00049  *   \begin{array}{ll}
00050  *     e^{-\pi ft/Q}\cos(2\pi ft) & \mbox{for $t\ge0$} \\
00051  *     0 & \mbox{for $t<0$}
00052  *   \end{array}
00053  *   \right.
00054  * \end{equation}
00055  * where the parameters $f$ and $Q$ are specified in the input structure.
00056  * The output must have an appropriate amount of memory allocated, and must
00057  * have the desired temporal spacing set.  Note: Ref.~\cite{JDECreighton}
00058  * used a different convention for the ringdown normlization: there the
00059  * ringdown waveform was taken to be $q(t)=(2\pi)^{1/2}r(t)$.
00060  * 
00061  * The routine \verb+LALComputeBlackHoleRing()+ computes a waveform for a
00062  * black hole with the specified physical parameters (in the input structure).
00063  * The parameters are the black hole mass $M$ (in solar masses $M_\odot$), the
00064  * spin $S={\hat{a}}GM^2/c$ expressed in terms of the dimensionless mass
00065  * parameter ${\hat{a}}$, the fractional mass lost $\epsilon$ in ringdown
00066  * radiation expressed as a percent, and the distance to the typical source
00067  * (angle-averaged waveform) $r$ given in megaparsecs (Mpc).  The central
00068  * frequency and quality of the ringdown are approximated
00069  * as~\cite{EWLeaver,FEcheverria}:
00070  * \begin{equation}
00071  *   f \simeq 32\,\textrm{kHz}\times[1-0.63(1-{\hat{a}})^{3/10}](M_\odot/M)
00072  * \end{equation}
00073  * and
00074  * \begin{equation}
00075  *   Q \simeq 2(1-{\hat{a}})^{-9/20}.
00076  * \end{equation}
00077  * The strain waveform produced is $h(t)=A_q q(t)$ where the amplitude factor
00078  * is~\cite{JDECreighton}
00079  * \begin{equation}
00080  *   A_q = 2.415\times10^{-21}Q^{-1/2}[1-0.63(1-{\hat{a}})^{3/10}]^{-1/2}
00081  *   \left(\frac{\textrm{Mpc}}{r}\right)
00082  *   \left(\frac{M}{M_\odot}\right)
00083  *   \left(\frac{\epsilon}{0.01}\right)^{1/2}.
00084  * \end{equation}
00085  * Note that this is written $A_q$ to emphasize that it is the amplitude
00086  * factor for $q(t)$ rather than $r(t)$.
00087  *
00088  * The routine \verb+LALCreateRingTemplateBank()+ creates a bank of ringdown
00089  * templates that cover a set range in the parameters $f$ and $Q$.  The bank
00090  * is destroyed with \verb+LALDestroyRingTemplateBank()+.
00091  * 
00092  * \subsubsection*{Algorithm}
00093  * 
00094  * The waveform generation routines use recurrance relations for both the
00095  * exponentially-decaying envelope and for the co-sinusoid.
00096  *
00097  * The template placement algorithm is described above.
00098  * 
00099  * \subsubsection*{Uses}
00100  * 
00101  * %% List of any external functions called by this function.
00102  * 
00103  * \subsubsection*{Notes}
00104  * 
00105  * %% Any relevant notes.
00106  * 
00107  * \vfill{\footnotesize\input{RingCV}}
00108  * 
00109  **** </lalLaTeX> */ 
00110 
00111 
00112 NRCSID( RINGC, "$Id: Ring.c,v 1.13 2008/08/21 14:23:52 lgoggin Exp $" );
00113 
00114 static REAL4 ring_spin_factor( REAL4 a )
00115 {
00116   return 1.0 - 0.63 * pow( 1.0 - a, 3.0/10.0 );
00117 }
00118 
00119 static REAL4 ring_quality_fn( REAL4 Q )
00120 {
00121     return  1.0 + 7.0/(24.0*Q*Q);
00122 }
00123 
00124 /*
00125  *
00126  * XLAL Routines.
00127  *
00128  */
00129 
00130 
00131 /* <lalVerbatim file="RingCP"> */
00132 REAL4 XLALBlackHoleRingSpin( REAL4 Q )
00133 /* </lalVerbatim> */
00134 {
00135   return 1.0 - pow( 2.0/Q, 20.0/9.0 );
00136 }
00137 
00138 /* <lalVerbatim file="RingCP"> */
00139 REAL4 XLALBlackHoleRingMass( REAL4 f, REAL4 Q )
00140 /* </lalVerbatim> */
00141 {
00142   const REAL4 c = LAL_C_SI;
00143   const REAL4 a = XLALBlackHoleRingSpin( Q );
00144   const REAL4 g = ring_spin_factor( a );
00145   return (c * c * c * g) / ( LAL_TWOPI * LAL_G_SI * LAL_MSUN_SI * f );
00146 }
00147 
00148 /* <lalVerbatim file="RingCP"> */
00149 REAL4 XLALBlackHoleRingQuality( REAL4 a )
00150 /* </lalVerbatim> */
00151 {
00152   return 2.0 * pow( ( 1.0 - a ), -0.45 );
00153 }
00154 
00155 /* <lalVerbatim file="RingCP"> */
00156 REAL4 XLALBlackHoleRingFrequency( REAL4 M, REAL4 a )
00157 /* </lalVerbatim> */
00158 {
00159   const REAL4 c = LAL_C_SI;
00160   const REAL4 g = ring_spin_factor( a );
00161   return (c * c * c * g) / ( LAL_TWOPI * LAL_G_SI * LAL_MSUN_SI * M );
00162 }
00163 
00164 
00165 /* <lalVerbatim file="RingCP"> */
00166 REAL4 XLALBlackHoleRingAmplitude( REAL4 f, REAL4 Q, REAL4 r, REAL4 epsilon )
00167 /* </lalVerbatim> */
00168 {
00169   const REAL4 c = LAL_C_SI;
00170   const REAL4 M = XLALBlackHoleRingMass( f, Q );
00171   const REAL4 a = XLALBlackHoleRingSpin( Q );
00172   const REAL4 g = ring_spin_factor( a );
00173   const REAL4 F = ring_quality_fn( Q );
00174 
00175   return sqrt(5.0/2.0 * epsilon) * 
00176     ( (LAL_G_SI * M * LAL_MSUN_SI) / ( c * c * r * 1.0e6 * LAL_PC_SI) ) *
00177     (1.0 / sqrt( Q * F * g) );
00178 }
00179 
00180 /* <lalVerbatim file="RingCP"> */
00181 REAL4 XLALBlackHoleRingEpsilon( REAL4 f, REAL4 Q, REAL4 r, REAL4 amplitude )
00182   /* </lalVerbatim> */
00183 {
00184   const REAL4 c = LAL_C_SI;
00185   const REAL4 M = XLALBlackHoleRingMass( f, Q );
00186   const REAL4 a = XLALBlackHoleRingSpin( Q );
00187   const REAL4 g = ring_spin_factor( a );
00188   const REAL4 F = ring_quality_fn( Q );
00189 
00190   return (2.0/5.0 * amplitude * amplitude) *
00191     pow( ( c * c * r * 1.0e6 * LAL_PC_SI) / (LAL_G_SI * M * LAL_MSUN_SI), 2 ) *
00192     ( Q * F * g );
00193 }
00194 
00195 /* <lalVerbatim file="RingCP"> */
00196 int XLALComputeRingTemplate( REAL4TimeSeries *output, SnglRingdownTable *input )
00197 /* </lalVerbatim> */
00198 {
00199   static const char *func = "XLALComputeRingTemplate";
00200   const REAL8 efolds = 10;
00201   REAL8 amp = 1.0;
00202   REAL8 fac;
00203   REAL8 a;
00204   REAL8 y;
00205   REAL8 yy;
00206   UINT4 i;
00207   UINT4 n;
00208 
00209   if ( ! output || ! output->data || ! input )
00210     XLAL_ERROR( func, XLAL_EFAULT );
00211 
00212   if ( ! output->data->length )
00213     XLAL_ERROR( func, XLAL_EBADLEN );
00214 
00215   if ( output->deltaT <= 0 || input->quality <= 0 || input->frequency <= 0 )
00216     XLAL_ERROR( func, XLAL_EINVAL );
00217 
00218   /* exponential decay variables */
00219   fac = exp( - LAL_PI * input->frequency * output->deltaT / input->quality );
00220   n = ceil( - efolds / log( fac ) );
00221 
00222   /* oscillator variables */
00223   a = 2 * cos( 2 * LAL_PI * input->frequency * output->deltaT );
00224   y = sin( -2 * LAL_PI * input->frequency * output->deltaT + 
00225       0.5 * LAL_PI + input->phase );
00226   yy = sin( -4 * LAL_PI * input->frequency * output->deltaT + 
00227       0.5 * LAL_PI + input->phase );
00228 
00229   if ( n < output->data->length )
00230     memset( output->data->data + n, 0,
00231         ( output->data->length - n ) * sizeof( *output->data->data ) );
00232   else
00233     n = output->data->length;
00234 
00235   for ( i = 0; i < n; ++i )
00236   {
00237     REAL4 tmp = a * y - yy;
00238     yy = y;
00239     output->data->data[i] = amp * ( y = tmp );
00240     amp *= fac;
00241   }
00242 
00243   return 0;
00244 }
00245 
00246 
00247 /* <lalVerbatim file="RingCP"> */
00248 int XLALComputeBlackHoleRing( 
00249     REAL4TimeSeries     *output, 
00250     SnglRingdownTable   *input,
00251     REAL4                dynRange
00252     )
00253 /* </lalVerbatim> */
00254 {
00255   static const char *func = "XLALComputeBlackHoleRing";
00256   const REAL4 amp = dynRange * 
00257     XLALBlackHoleRingAmplitude( 
00258         input->frequency, input->quality, input->eff_dist, input->epsilon );
00259   UINT4 i;
00260 
00261   if ( XLALComputeRingTemplate( output, input ) < 0 )
00262     XLAL_ERROR( func, XLAL_EFUNC );
00263 
00264   for ( i = 0; i < output->data->length; ++i )
00265     output->data->data[i] *= amp;
00266   
00267   return 0;
00268 }
00269 
00270 
00271 static int MakeBank( SnglRingdownTable *tmplt, RingTemplateBankInput *input )
00272 {
00273   UINT4 count = 0;
00274   REAL4 dseff = 4 * sqrt( input->maxMismatch );
00275   REAL4 minlogf = log( input->minFrequency );
00276   REAL4 maxlogf = log( input->maxFrequency );
00277   REAL4 q = input->minQuality;
00278 
00279   while ( q < input->maxQuality )
00280   {
00281     REAL4 q2 = q * q;
00282     REAL4 logfreq = minlogf;
00283 
00284     while ( logfreq < maxlogf )
00285     {
00286       if ( tmplt )
00287       {
00288         tmplt[count].quality   = q;
00289         tmplt[count].frequency = exp( logfreq );
00290         tmplt[count].phase     = input->templatePhase;
00291         tmplt[count].epsilon   = input->templateEpsilon;
00292         tmplt[count].eff_dist  = input->templateDistance;
00293       }
00294       ++count;
00295       logfreq += dseff / sqrt( 3 + 8 * q2 );
00296     }
00297 
00298     q += dseff * q * ( 1 + 4 * q2 ) / sqrt( 3 + 16 * q2 * q2 );
00299   }
00300 
00301   return count;
00302 }
00303 
00304 
00305 /* <lalVerbatim file="RingCP"> */
00306 RingTemplateBank *XLALCreateRingTemplateBank( RingTemplateBankInput *input )
00307 /* </lalVerbatim> */
00308 {
00309   static const char *func = "XLALCreateRingTemplateBank";
00310   UINT4 i;
00311   RingTemplateBank *bank;
00312 
00313   if ( ! input )
00314     XLAL_ERROR_NULL( func, XLAL_EFAULT );
00315 
00316   bank = LALCalloc( 1, sizeof( *bank ) );
00317   if ( ! bank )
00318     XLAL_ERROR_NULL( func, XLAL_ENOMEM );
00319 
00320   bank->numTmplt = MakeBank( NULL, input );
00321   bank->tmplt = LALCalloc( bank->numTmplt, sizeof( *bank->tmplt ) );
00322   if ( ! bank->tmplt )
00323   {
00324     LALFree( bank );
00325     XLAL_ERROR_NULL( func, XLAL_ENOMEM );
00326   }
00327   for ( i = 0; i < bank->numTmplt - 1; ++i )
00328     bank->tmplt[i].next = bank->tmplt + i + 1;
00329 
00330   MakeBank( bank->tmplt, input );
00331   return bank;
00332 }
00333 
00334 
00335 /* <lalVerbatim file="RingCP"> */
00336 void XLALDestroyRingTemplateBank( RingTemplateBank *bank )
00337 /* </lalVerbatim> */
00338 {
00339   if ( bank )
00340   {
00341     if ( bank->tmplt )
00342       LALFree( bank->tmplt );
00343     LALFree( bank );
00344   }
00345   return;
00346 }

Generated on Sun Sep 7 03:07:10 2008 for LAL by  doxygen 1.5.2