LALPulsar  6.1.0.1-89842e6
GenerateTaylorCW.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2007 Teviet Creighton
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with with program; see the file COPYING. If not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 */
19 
20 #include <lal/LALStdio.h>
21 #include <lal/LALStdlib.h>
22 #include <lal/LALConstants.h>
23 #include <lal/Units.h>
24 #include <lal/AVFactories.h>
25 #include <lal/SeqFactories.h>
26 #include <lal/PulsarSimulateCoherentGW.h>
27 #include <lal/GenerateTaylorCW.h>
28 
29 /**
30  * \author Creighton, T. D.
31  *
32  * \brief Computes a Taylor-parametrized continuous waveform.
33  *
34  * ### Description ###
35  *
36  * This function computes a quaiperiodic waveform using the parameters in
37  * <tt>*params</tt>, storing the result in <tt>*output</tt>.
38  *
39  * In the <tt>*params</tt> structure, the routine uses all the "input"
40  * fields specified in \c TaylorCWParamStruc, and sets all of the
41  * "output" fields. If <tt>params->f=NULL</tt>, a precisely periodic
42  * (monochromatic) waveform is generated.
43  *
44  * In the <tt>*output</tt> structure, the field <tt>output->h</tt> is
45  * ignored, but all other pointer fields must be set to \c NULL. The
46  * function will create and allocate space for <tt>output->a</tt>,
47  * <tt>output->f</tt>, and <tt>output->phi</tt> as necessary. The
48  * <tt>output->shift</tt> field will remain set to \c NULL.
49  *
50  * ### Algorithm ###
51  *
52  * This function is a fairly straightforward calculation of
53  * \eqref{eq_taylorcw-freq} and \eqref{eq_taylorcw-phi} in
54  * \ref GenerateTaylorCW_h. There are no real tricks involved, except
55  * to note that the phase \f$ \phi \f$ and the time elapsed \f$ t-t_0 \f$ are
56  * computed and stored as \c REAL8s in order to provide waveforms
57  * that are accurate to small fractions of a cycle over many years.
58  *
59  * Since the waveform does not include any effects such as precession,
60  * the amplitudes \f$ A_+ \f$ , \f$ A_\times \f$ and the shift angle \f$ \Phi \f$ , as
61  * defined in \ref PulsarSimulateCoherentGW_h, are constant. This is dealt
62  * with by setting <tt>output->a</tt> to be a
63  * \c REAL4TimeVectorSequence of two identical vectors
64  * \f$ (A_+,A_\times) \f$ spanning the requested time of the waveform, under
65  * the assumption that any routine using this output data (such as the
66  * routines in \ref PulsarSimulateCoherentGW_h) will interpolate these two
67  * endpoints to get the instantaneous values of \f$ A_+ \f$ , \f$ A_\times \f$ . The
68  * field <tt>output->shift</tt> is left as \c NULL, so the constant
69  * value of \f$ \Phi \f$ must be subsumed into the polarization angle \f$ \psi \f$ .
70  *
71  * The fields <tt>output->f</tt> and <tt>output->phi</tt> are created and
72  * filled at the requested sampling interval <tt>params->deltaT</tt>; it is
73  * up to the calling routine to ensure that this sampling interval is
74  * reasonable. As a guideline, we want to be able to determine the
75  * instantaneous wave phase accurately to within a fraction of a cycle.
76  * For functions that compute the phase by linear interpolation of
77  * <tt>output->phi</tt>, this means sampling on timescales \f$ \Delta
78  * t\lesssim\dot{f}^{-1/2}\sim\max\{\sqrt{kf_0f_kT^{k-1}}\} \f$ , where \f$ T \f$ is
79  * the duration of the waveform. More precisely, the largest deviation
80  * from linear phase evolution will typically be on the order of
81  * \f$ \Delta\phi\approx(1/2)\ddot{\phi}(\Delta t/2)^2\approx(\pi/4)\Delta
82  * f\Delta t \f$ , where \f$ \Delta f \f$ is the frequency shift over the timestep.
83  * So if we want our interpolated phase to agree with the true phase to
84  * within, say, \f$ \pi/2 \f$ radians, then we would like to have
85  * \f[
86  * \Delta f \Delta t \lesssim 2 \;.
87  * \f]
88  * This routine provides a check by setting the output parameter field
89  * <tt>params->dfdt</tt> equal to the maximum value of \f$ \Delta f\Delta t \f$
90  * encountered during the integration.
91  *
92  */
93 void
97 {
98  UINT4 n, i; /* number of and index over samples */
99  UINT4 nSpin = 0, j; /* number of and index over spindown terms */
100  REAL8 t, tPow, dt; /* time, interval, and t raised to a power */
101  REAL8 f0, phi0; /* initial phase and frequency */
102  REAL8 twopif0; /* 2*pi*f0 */
103  REAL8 f, fPrev; /* current and previous values of frequency */
104  REAL4 df = 0.0; /* maximum difference between f and fPrev */
105  REAL8 phi; /* current value of phase */
106  REAL8 *fSpin = NULL; /* pointer to Taylor coefficients */
107  REAL4 *fData; /* pointer to frequency data */
108  REAL8 *phiData; /* pointer to phase data */
109 
110  INITSTATUS( stat );
112 
113  /* Make sure parameter and output structures exist. */
115  GENERATETAYLORCWH_MSGENUL );
117  GENERATETAYLORCWH_MSGENUL );
118 
119  /* Make sure output fields don't exist. */
121  GENERATETAYLORCWH_MSGEOUT );
123  GENERATETAYLORCWH_MSGEOUT );
125  GENERATETAYLORCWH_MSGEOUT );
126  ASSERT( !( output->shift ), stat, GENERATETAYLORCWH_EOUT,
127  GENERATETAYLORCWH_MSGEOUT );
128 
129  /* If Taylor coeficients are specified, make sure they exist. */
130  if ( params->f ) {
132  GENERATETAYLORCWH_MSGENUL );
133  nSpin = params->f->length;
134  fSpin = params->f->data;
135  }
136 
137  /* Set up some other constants, to avoid repeated dereferencing. */
138  n = params->length;
139  dt = params->deltaT;
140  f0 = fPrev = params->f0;
141  twopif0 = f0 * LAL_TWOPI;
142  phi0 = params->phi0;
143 
144  /* Allocate output structures. */
145  if ( ( output->a = ( REAL4TimeVectorSeries * )
146  LALMalloc( sizeof( REAL4TimeVectorSeries ) ) ) == NULL ) {
147  ABORT( stat, GENERATETAYLORCWH_EMEM, GENERATETAYLORCWH_MSGEMEM );
148  }
149  memset( output->a, 0, sizeof( REAL4TimeVectorSeries ) );
150  if ( ( output->f = ( REAL4TimeSeries * )
151  LALMalloc( sizeof( REAL4TimeSeries ) ) ) == NULL ) {
152  LALFree( output->a );
153  output->a = NULL;
154  ABORT( stat, GENERATETAYLORCWH_EMEM, GENERATETAYLORCWH_MSGEMEM );
155  }
156  memset( output->f, 0, sizeof( REAL4TimeSeries ) );
157  if ( ( output->phi = ( REAL8TimeSeries * )
158  LALMalloc( sizeof( REAL8TimeSeries ) ) ) == NULL ) {
159  LALFree( output->a );
160  output->a = NULL;
161  LALFree( output->f );
162  output->f = NULL;
163  ABORT( stat, GENERATETAYLORCWH_EMEM, GENERATETAYLORCWH_MSGEMEM );
164  }
165  memset( output->phi, 0, sizeof( REAL8TimeSeries ) );
166 
167  /* Set output structure metadata fields. */
168  output->position = params->position;
169  output->psi = params->psi;
170  output->a->epoch = output->f->epoch = output->phi->epoch
171  = params->epoch;
172  output->a->deltaT = n * params->deltaT;
173  output->f->deltaT = output->phi->deltaT = params->deltaT;
174  output->a->sampleUnits = lalStrainUnit;
175  output->f->sampleUnits = lalHertzUnit;
176  output->phi->sampleUnits = lalDimensionlessUnit;
177  snprintf( output->a->name, LALNameLength, "CW amplitudes" );
178  snprintf( output->f->name, LALNameLength, "CW frequency" );
179  snprintf( output->phi->name, LALNameLength, "CW phase" );
180 
181  /* Allocate phase and frequency arrays. */
182  LALSCreateVector( stat->statusPtr, &( output->f->data ), n );
183  BEGINFAIL( stat ) {
184  LALFree( output->a );
185  output->a = NULL;
186  LALFree( output->f );
187  output->f = NULL;
188  LALFree( output->phi );
189  output->phi = NULL;
190  }
191  ENDFAIL( stat );
192  LALDCreateVector( stat->statusPtr, &( output->phi->data ), n );
193  BEGINFAIL( stat ) {
194  TRY( LALSDestroyVector( stat->statusPtr, &( output->f->data ) ),
195  stat );
196  LALFree( output->a );
197  output->a = NULL;
198  LALFree( output->f );
199  output->f = NULL;
200  LALFree( output->phi );
201  output->phi = NULL;
202  }
203  ENDFAIL( stat );
204 
205  /* Allocate and fill amplitude array. */
206  {
207  CreateVectorSequenceIn in; /* input to create output->a */
208  in.length = 2;
209  in.vectorLength = 2;
210  LALSCreateVectorSequence( stat->statusPtr, &( output->a->data ), &in );
211  BEGINFAIL( stat ) {
212  TRY( LALSDestroyVector( stat->statusPtr, &( output->f->data ) ),
213  stat );
214  TRY( LALDDestroyVector( stat->statusPtr, &( output->phi->data ) ),
215  stat );
216  LALFree( output->a );
217  output->a = NULL;
218  LALFree( output->f );
219  output->f = NULL;
220  LALFree( output->phi );
221  output->phi = NULL;
222  }
223  ENDFAIL( stat );
224  output->a->data->data[0] = output->a->data->data[2] = params->aPlus;
225  output->a->data->data[1] = output->a->data->data[3] = params->aCross;
226  }
227 
228  /* Fill frequency and phase arrays. */
229  fData = output->f->data->data;
230  phiData = output->phi->data->data;
231 
232  for ( i = 0; i < n; i++ ) {
233  t = tPow = i * dt;
234  f = 1.0;
235  phi = t;
236  j = 0;
237  while ( j < nSpin ) {
238  f += fSpin[j] * tPow;
239  phi += fSpin[j] * ( tPow *= t ) / ( j + 2.0 );
240  j++;
241  }
242  f *= f0;
243  phi *= twopif0;
244  if ( fabs( f - fPrev ) > df ) {
245  df = fabs( f - fPrev );
246  }
247  *( fData++ ) = fPrev = f;
248  *( phiData++ ) = phi + phi0;
249  }
250 
251  /* Set output field and return. */
252  params->dfdt = df * dt;
254  RETURN( stat );
255 }
int j
#define LALMalloc(n)
#define LALFree(p)
#define ABORT(statusptr, code, mesg)
#define ENDFAIL(statusptr)
#define TRY(func, statusptr)
#define ATTATCHSTATUSPTR(statusptr)
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
#define BEGINFAIL(statusptr)
void LALSCreateVectorSequence(LALStatus *status, REAL4VectorSequence **vectorSequence, CreateVectorSequenceIn *vSeqParams)
#define GENERATETAYLORCWH_EOUT
Output field a, f, phi, or shift already exists.
#define GENERATETAYLORCWH_ENUL
Unexpected null pointer in arguments.
#define GENERATETAYLORCWH_EMEM
Out of memory.
void LALGenerateTaylorCW(LALStatus *stat, PulsarCoherentGW *output, TaylorCWParamStruc *params)
Computes a Taylor-parametrized continuous waveform.
#define LAL_TWOPI
double REAL8
uint32_t UINT4
float REAL4
LALNameLength
const LALUnit lalStrainUnit
const LALUnit lalHertzUnit
const LALUnit lalDimensionlessUnit
void LALDCreateVector(LALStatus *, REAL8Vector **, UINT4)
void LALDDestroyVector(LALStatus *, REAL8Vector **)
void LALSDestroyVector(LALStatus *, REAL4Vector **)
void LALSCreateVector(LALStatus *, REAL4Vector **, UINT4)
n
This structure stores a representation of a plane gravitational wave propagating from a particular po...
This structure stores the parameters for constructing a gravitational waveform with a Taylor-polynomi...
LIGOTimeGPS epoch
double psi
double df