LALSimulation  5.4.0.1-fe68b98
LALSimIMRSEOBNRROMUtilities.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014, 2015 Michael Puerrer, John Veitch
3  * Reduced Order Model for SEOBNR
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with with program; see the file COPYING. If not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301 USA
19  */
20 
21 /**
22  * \author Michael Puerrer
23  *
24  * \file
25  *
26  * \brief Auxiliary functions for SEOBNRv1/v2 reduced order modeling codes in
27  * LALSimIMRSEOBNRv2ROMDoubleSpin.c, LALSimIMRSEOBNRv1ROMDoubleSpin.c,
28  * LALSimIMRSEOBNRv2ROMEffectiveSpin.c, LALSimIMRSEOBNRv1ROMEffectiveSpin.c,
29  * LALSimIMRSEOBNRv2ChirpTime.c, LALSimIMRSEOBNRv2ROMDoubleSpinHI.c.
30  *
31  * Here I collect common auxiliary functions pertaining to reading
32  * data stored in gsl binary vectors and matrices, HDF5 files using the LAL interface,
33  * parameter space interpolation with B-splines, fitting to a cubic,
34  * a custom gsl error handler and adjustment of nearby parameter values.
35  */
36 
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <lal/XLALError.h>
40 #include <stdbool.h>
41 #include <gsl/gsl_math.h>
42 #include <gsl/gsl_multifit.h>
43 #include <gsl/gsl_interp.h>
44 #include <gsl/gsl_fit.h>
46 
47 #ifdef LAL_HDF5_ENABLED
48 #include <lal/H5FileIO.h>
49 #endif
50 
51 UNUSED static int read_vector(const char dir[], const char fname[], gsl_vector *v);
52 UNUSED static int read_matrix(const char dir[], const char fname[], gsl_matrix *m);
53 /* SEOBNRv4HM_ROM functions */
54 UNUSED static char* concatenate_strings(int count, ...);
55 UNUSED static REAL8 sigmoid(REAL8 x);
56 UNUSED static UINT4 blend(gsl_vector * freqs, gsl_vector * out_fun, REAL8 freq_1, REAL8 freq_2);
57 UNUSED static UINT4 blend_functions(gsl_vector * freqs_out, gsl_vector * out_fun, gsl_vector * freq_in_1, gsl_vector * fun_in_1, gsl_vector * freq_in_2, gsl_vector * fun_in_2, REAL8 freq_1, REAL8 freq_2);
58 UNUSED static UINT4 compute_i_max_LF_i_min_HF(INT8 * i_max_LF, INT8 * i_min_LF,gsl_vector * freqs_in_1,gsl_vector * freqs_in_2,REAL8 freq_1);
59 UNUSED static REAL8 Get_omegaQNM_SEOBNRv4(REAL8 q, REAL8 chi1z, REAL8 chi2z, UINT4 l, UINT4 m);
60 UNUSED static REAL8 Get_omegaQNM_SEOBNRv5(REAL8 q, REAL8 chi1z, REAL8 chi2z, UINT4 l, UINT4 m);
61 UNUSED static UINT4 unwrap_phase(gsl_vector* phaseout,gsl_vector* phasein);
62 UNUSED static UINT8 compute_i_at_f(gsl_vector * freq_array, REAL8 freq);
63 UNUSED static UINT4 align_wfs_window(gsl_vector* f_array_1, gsl_vector* f_array_2, gsl_vector* phase_1, gsl_vector* phase_2, REAL8* Deltat, REAL8* Deltaphi, REAL8 f_align_start, REAL8 f_align_end);
64 UNUSED static UINT4 align_wfs_window_from_22(gsl_vector* f_array_1, gsl_vector* f_array_2, gsl_vector* phase_1, gsl_vector* phase_2, REAL8 f_align_start, REAL8 f_align_end, REAL8 Deltat22, REAL8 Deltaphi22, INT4 modeM);
65 
66 #ifdef LAL_HDF5_ENABLED
67 UNUSED static int CheckVectorFromHDF5(LALH5File *file, const char name[], const double *v, size_t n);
68 UNUSED static int ReadHDF5RealVectorDataset(LALH5File *file, const char *name, gsl_vector **data);
69 UNUSED static int ReadHDF5RealMatrixDataset(LALH5File *file, const char *name, gsl_matrix **data);
70 UNUSED static int ReadHDF5LongVectorDataset(LALH5File *file, const char *name, gsl_vector_long **data);
71 UNUSED static int ReadHDF5LongMatrixDataset(LALH5File *file, const char *name, gsl_matrix_long **data);
72 UNUSED static void PrintInfoStringAttribute(LALH5File *file, const char attribute[]);
73 UNUSED static int ROM_check_version_number(LALH5File *file, INT4 version_major_in, INT4 version_minor_in, INT4 version_micro_in);
74 UNUSED static int ROM_check_canonical_file_basename(LALH5File *file, const char file_name[], const char attribute[]);
75 #endif
76 
78  gsl_vector *v,
79  REAL8 eta,
80  REAL8 chi1,
81  REAL8 chi2,
82  int ncy,
83  int ncz,
84  gsl_bspline_workspace *bwx,
85  gsl_bspline_workspace *bwy,
86  gsl_bspline_workspace *bwz
87 );
88 
90  gsl_vector *v,
91  REAL8 eta,
92  REAL8 chi,
93  int ncx,
94  int ncy,
95  gsl_bspline_workspace *bwx,
96  gsl_bspline_workspace *bwy
97 );
98 
99 UNUSED static gsl_vector *Fit_cubic(const gsl_vector *xi, const gsl_vector *yi);
100 
101 UNUSED static bool approximately_equal(REAL8 x, REAL8 y, REAL8 epsilon);
102 UNUSED static void nudge(REAL8 *x, REAL8 X, REAL8 epsilon);
103 
104 UNUSED static double SEOBNRROM_Ringdown_Mf_From_Mtot_q(
105  const double Mtot_sec,
106  const double q,
107  const double chi1,
108  const double chi2,
109  Approximant apx
110 );
111 UNUSED static double SEOBNRROM_Ringdown_Mf_From_Mtot_Eta(
112  const double Mtot_sec,
113  const double eta,
114  const double chi1,
115  const double chi2,
116  Approximant apx
117 );
118 
119 // Helper functions to read gsl_vector and gsl_matrix data with error checking
120 static int read_vector(const char dir[], const char fname[], gsl_vector *v) {
121  size_t size = strlen(dir) + strlen(fname) + 2;
122  char *path = XLALMalloc(size);
123  snprintf(path, size, "%s/%s", dir, fname);
124 
125  FILE *f = fopen(path, "rb");
126  if (!f)
127  XLAL_ERROR(XLAL_EIO, "Could not find ROM data file at path `%s'", path);
128  int ret = gsl_vector_fread(f, v);
129  if (ret != 0)
130  XLAL_ERROR(XLAL_EIO, "Error reading data from `%s'", path);
131  fclose(f);
132 
133  XLAL_PRINT_INFO("Sucessfully read data file `%s'", path);
134  XLALFree(path);
135  return(XLAL_SUCCESS);
136 }
137 
138 static int read_matrix(const char dir[], const char fname[], gsl_matrix *m) {
139  size_t size = strlen(dir) + strlen(fname) + 2;
140  char *path = XLALMalloc(size);
141  snprintf(path, size, "%s/%s", dir, fname);
142 
143  FILE *f = fopen(path, "rb");
144  if (!f)
145  XLAL_ERROR(XLAL_EIO, "Could not find ROM data file at path `%s'", path);
146  int ret = gsl_matrix_fread(f, m);
147  if (ret != 0)
148  XLAL_ERROR(XLAL_EIO, "Error reading data from `%s'", path);
149  fclose(f);
150 
151  XLAL_PRINT_INFO("Sucessfully read data file `%s'", path);
152  XLALFree(path);
153  return(XLAL_SUCCESS);
154 }
155 
156 #ifdef LAL_HDF5_ENABLED
157 static int CheckVectorFromHDF5(LALH5File *file, const char name[], const double *v, size_t n) {
158  gsl_vector *temp = NULL;
159  ReadHDF5RealVectorDataset(file, name, &temp);
160 
161  if (temp->size != n)
162  XLAL_ERROR(XLAL_EIO, "Length of data %s disagrees", name);
163 
164  for (size_t i=0; i<temp->size; i++)
165  if (gsl_vector_get(temp, i) != v[i])
166  XLAL_ERROR(XLAL_EIO, "Data %s disagrees", name);
167  gsl_vector_free(temp);
168  return XLAL_SUCCESS;
169 }
170 
171 static int ReadHDF5RealVectorDataset(LALH5File *file, const char *name, gsl_vector **data) {
172  LALH5Dataset *dset;
173  UINT4Vector *dimLength;
174  size_t n;
175 
176  if (file == NULL || name == NULL || data == NULL)
178 
179  dset = XLALH5DatasetRead(file, name);
180  if (dset == NULL)
182 
184  XLALH5DatasetFree(dset);
185  XLAL_ERROR(XLAL_ETYPE, "Dataset `%s' is wrong type", name);
186  }
187 
188  dimLength = XLALH5DatasetQueryDims(dset);
189  if (dimLength == NULL) {
190  XLALH5DatasetFree(dset);
192  }
193  if (dimLength->length != 1) {
194  XLALH5DatasetFree(dset);
195  XLAL_ERROR(XLAL_EDIMS, "Dataset `%s' must be 1-dimensional", name);
196  }
197 
198  n = dimLength->data[0];
199  XLALDestroyUINT4Vector(dimLength);
200 
201  if (*data == NULL) {
202  *data = gsl_vector_alloc(n);
203  if (*data == NULL) {
204  XLALH5DatasetFree(dset);
205  XLAL_ERROR(XLAL_ENOMEM, "gsl_vector_alloc(%zu) failed", n);
206  }
207  }
208  else if ((*data)->size != n) {
209  XLALH5DatasetFree(dset);
210  XLAL_ERROR(XLAL_EINVAL, "Expected gsl_vector `%s' of size %zu", name, n);
211  }
212 
213  // Now read the data
214  if (XLALH5DatasetQueryData((*data)->data, dset) < 0) {
215  XLALH5DatasetFree(dset);
217  }
218 
219  XLALH5DatasetFree(dset);
220  return 0;
221 }
222 
223 static int ReadHDF5RealMatrixDataset(LALH5File *file, const char *name, gsl_matrix **data) {
224  LALH5Dataset *dset;
225  UINT4Vector *dimLength;
226  size_t n1, n2;
227 
228  if (file == NULL || name == NULL || data == NULL)
230 
231  dset = XLALH5DatasetRead(file, name);
232  if (dset == NULL)
234 
236  XLALH5DatasetFree(dset);
237  XLAL_ERROR(XLAL_ETYPE, "Dataset `%s' is wrong type", name);
238  }
239 
240  dimLength = XLALH5DatasetQueryDims(dset);
241  if (dimLength == NULL) {
242  XLALH5DatasetFree(dset);
244  }
245  if (dimLength->length != 2) {
246  XLALH5DatasetFree(dset);
247  XLAL_ERROR(XLAL_EDIMS, "Dataset `%s' must be 2-dimensional", name);
248  }
249 
250  n1 = dimLength->data[0];
251  n2 = dimLength->data[1];
252  XLALDestroyUINT4Vector(dimLength);
253 
254  if (*data == NULL) {
255  *data = gsl_matrix_alloc(n1, n2);
256  if (*data == NULL) {
257  XLALH5DatasetFree(dset);
258  XLAL_ERROR(XLAL_ENOMEM, "gsl_matrix_alloc(%zu, %zu) failed", n1, n2);
259  }
260  }
261  else if ((*data)->size1 != n1 || (*data)->size2 != n2) {
262  XLALH5DatasetFree(dset);
263  XLAL_ERROR(XLAL_EINVAL, "Expected gsl_matrix `%s' of size %zu x %zu", name, n1, n2);
264  }
265 
266  // Now read the data
267  if (XLALH5DatasetQueryData((*data)->data, dset) < 0) {
268  XLALH5DatasetFree(dset);
270  }
271 
272  XLALH5DatasetFree(dset);
273  return 0;
274 }
275 
276 static int ReadHDF5LongVectorDataset(LALH5File *file, const char *name, gsl_vector_long **data) {
277  LALH5Dataset *dset;
278  UINT4Vector *dimLength;
279  size_t n;
280 
281  if (file == NULL || name == NULL || data == NULL)
283 
284  dset = XLALH5DatasetRead(file, name);
285  if (dset == NULL)
287 
289  XLALH5DatasetFree(dset);
290  XLAL_ERROR(XLAL_ETYPE, "Dataset `%s' is wrong type", name);
291  }
292 
293  dimLength = XLALH5DatasetQueryDims(dset);
294  if (dimLength == NULL) {
295  XLALH5DatasetFree(dset);
297  }
298  if (dimLength->length != 1) {
299  XLALH5DatasetFree(dset);
300  XLAL_ERROR(XLAL_EDIMS, "Dataset `%s' must be 1-dimensional", name);
301  }
302 
303  n = dimLength->data[0];
304  XLALDestroyUINT4Vector(dimLength);
305 
306  if (*data == NULL) {
307  *data = gsl_vector_long_alloc(n);
308  if (*data == NULL) {
309  XLALH5DatasetFree(dset);
310  XLAL_ERROR(XLAL_ENOMEM, "gsl_vector_long_alloc(%zu) failed", n);
311  }
312  }
313  else if ((*data)->size != n) {
314  XLALH5DatasetFree(dset);
315  XLAL_ERROR(XLAL_EINVAL, "Expected gsl_vector `%s' of size %zu", name, n);
316  }
317 
318  // Now read the data
319  if (XLALH5DatasetQueryData((*data)->data, dset) < 0) {
320  XLALH5DatasetFree(dset);
322  }
323 
324  XLALH5DatasetFree(dset);
325  return 0;
326 }
327 
328 static int ReadHDF5LongMatrixDataset(LALH5File *file, const char *name, gsl_matrix_long **data) {
329  LALH5Dataset *dset;
330  UINT4Vector *dimLength;
331  size_t n1, n2;
332 
333  if (file == NULL || name == NULL || data == NULL)
335 
336  dset = XLALH5DatasetRead(file, name);
337  if (dset == NULL)
339 
341  XLALH5DatasetFree(dset);
342  XLAL_ERROR(XLAL_ETYPE, "Dataset `%s' is wrong type", name);
343  }
344 
345  dimLength = XLALH5DatasetQueryDims(dset);
346  if (dimLength == NULL) {
347  XLALH5DatasetFree(dset);
349  }
350  if (dimLength->length != 2) {
351  XLALH5DatasetFree(dset);
352  XLAL_ERROR(XLAL_EDIMS, "Dataset `%s' must be 2-dimensional", name);
353  }
354 
355  n1 = dimLength->data[0];
356  n2 = dimLength->data[1];
357  XLALDestroyUINT4Vector(dimLength);
358 
359  if (*data == NULL) {
360  *data = gsl_matrix_long_alloc(n1, n2);
361  if (*data == NULL) {
362  XLALH5DatasetFree(dset);
363  XLAL_ERROR(XLAL_ENOMEM, "gsl_matrix_long_alloc(%zu, %zu) failed", n1, n2);
364  }
365  }
366  else if ((*data)->size1 != n1 || (*data)->size2 != n2) {
367  XLALH5DatasetFree(dset);
368  XLAL_ERROR(XLAL_EINVAL, "Expected gsl_matrix_long `%s' of size %zu x %zu", name, n1, n2);
369  }
370 
371  // Now read the data
372  if (XLALH5DatasetQueryData((*data)->data, dset) < 0) {
373  XLALH5DatasetFree(dset);
375  }
376 
377  XLALH5DatasetFree(dset);
378  return 0;
379 }
380 
381 static void PrintInfoStringAttribute(LALH5File *file, const char attribute[]) {
382  LALH5Generic gfile = {.file = file};
383  int len = XLALH5AttributeQueryStringValue(NULL, 0, gfile, attribute) + 1;
384  char *str = XLALMalloc(len);
385  XLALH5FileQueryStringAttributeValue(str, len, file, attribute);
386  XLALPrintInfo("%s:\n%s\n", attribute, str);
387  LALFree(str);
388 }
389 
390 static int ROM_check_version_number(LALH5File *file, INT4 version_major_in, INT4 version_minor_in, INT4 version_micro_in) {
391  INT4 version_major;
392  INT4 version_minor;
393  INT4 version_micro;
394 
395  LALH5Generic gfile = {.file = file};
396  XLALH5AttributeQueryScalarValue(&version_major, gfile, "version_major");
397  XLALH5AttributeQueryScalarValue(&version_minor, gfile, "version_minor");
398  XLALH5AttributeQueryScalarValue(&version_micro, gfile, "version_micro");
399 
400  if ((version_major_in != version_major) || (version_minor_in != version_minor) || (version_micro_in != version_micro)) {
401  XLAL_ERROR(XLAL_EIO, "Expected ROM data version %d.%d.%d, but got version %d.%d.%d.",
402  version_major_in, version_minor_in, version_micro_in, version_major, version_minor, version_micro);
403  }
404  else {
405  XLALPrintInfo("Reading ROM data version %d.%d.%d.\n", version_major, version_minor, version_micro);
406  return XLAL_SUCCESS;
407  }
408 }
409 
410 static int ROM_check_canonical_file_basename(LALH5File *file, const char file_name[], const char attribute[]) {
411 
412  LALH5Generic gfile = {.file = file};
413  int len = XLALH5AttributeQueryStringValue(NULL, 0, gfile, attribute) + 1;
414  char *canonical_file_basename = XLALMalloc(len);
415  XLALH5FileQueryStringAttributeValue(canonical_file_basename, len, file, attribute);
416 
417  if (strcmp(canonical_file_basename, file_name) != 0) {
418  XLAL_ERROR(XLAL_EIO, "Expected CANONICAL_FILE_BASENAME %s, but got %s.",
419  canonical_file_basename, file_name);
420  }
421  else {
422  XLALPrintInfo("ROM canonical_file_basename %s\n", canonical_file_basename);
423  }
424  XLALFree(canonical_file_basename);
425  return XLAL_SUCCESS;
426 }
427 #endif
428 
429 // Helper function to perform tensor product spline interpolation with gsl
430 // The gsl_vector v contains the ncx x ncy x ncz dimensional coefficient tensor in vector form
431 // that should be interpolated and evaluated at position (eta,chi1,chi2).
433  gsl_vector *v,
434  REAL8 eta,
435  REAL8 chi1,
436  REAL8 chi2,
437  int ncy,
438  int ncz,
439  gsl_bspline_workspace *bwx,
440  gsl_bspline_workspace *bwy,
441  gsl_bspline_workspace *bwz
442 ) {
443  // Store nonzero cubic (order k=4) B-spline basis functions in the eta and chi directions.
444  gsl_vector *Bx4 = gsl_vector_alloc(4);
445  gsl_vector *By4 = gsl_vector_alloc(4);
446  gsl_vector *Bz4 = gsl_vector_alloc(4);
447 
448  size_t isx, isy, isz; // first non-zero spline
449  size_t iex, iey, iez; // last non-zero spline
450  // Evaluate all potentially nonzero cubic B-spline basis functions for
451  // positions (eta,chi) and store them in the vectors Bx4, By4, Bz4.
452  // Since the B-splines are of compact support we only need to store a small
453  // number of basis functions to avoid computing terms that would be zero anyway.
454  // https://www.gnu.org/software/gsl/manual/html_node/Overview-of-B_002dsplines.html#Overview-of-B_002dsplines
455  gsl_bspline_eval_nonzero(eta, Bx4, &isx, &iex, bwx);
456  gsl_bspline_eval_nonzero(chi1, By4, &isy, &iey, bwy);
457  gsl_bspline_eval_nonzero(chi2, Bz4, &isz, &iez, bwz);
458 
459  // Now compute coefficient at desired parameters (q,chi1,chi2)
460  // from C(eta,chi1,chi2) = c_ijk * Beta_i * Bchi1_j * Bchi2_k
461  // while summing over indices i,j,k where the B-splines are nonzero.
462  // Note: in the 2D case we were able to use gsl_matrix c = gsl_matrix_view_vector(&v, ncx, ncy).matrix
463  // to convert vector view of the coefficient matrix to a matrix view.
464  // However, since tensors are not supported in gsl, we have to do the indexing explicitly.
465  double sum = 0;
466  for (int i=0; i<4; i++)
467  for (int j=0; j<4; j++)
468  for (int k=0; k<4; k++) {
469  int ii = isx + i;
470  int jj = isy + j;
471  int kk = isz + k;
472  double cijk = gsl_vector_get(v, (ii*ncy + jj)*ncz + kk);
473  sum += cijk * gsl_vector_get(Bx4, i) * gsl_vector_get(By4, j) * gsl_vector_get(Bz4, k);
474  }
475 
476  gsl_vector_free(Bx4);
477  gsl_vector_free(By4);
478  gsl_vector_free(Bz4);
479 
480  return sum;
481 }
482 
483 // Helper function to perform tensor product spline interpolation with gsl
484 // The gsl_vector v contains the ncx x ncy dimensional coefficient matrix in vector form
485 // that should be interpolated and evaluated at position (eta,chi).
487  gsl_vector *v,
488  REAL8 eta,
489  REAL8 chi,
490  int ncx,
491  int ncy,
492  gsl_bspline_workspace *bwx,
493  gsl_bspline_workspace *bwy
494 ) {
495  gsl_matrix c = gsl_matrix_view_vector(v, ncx, ncy).matrix; // Convert coefficient matrix from vector view to matrix view c_ij.
496 
497  // Store nonzero cubic (order k=4) B-spline basis functions in the eta and chi directions.
498  gsl_vector *Bx4 = gsl_vector_alloc(4);
499  gsl_vector *By4 = gsl_vector_alloc(4);
500 
501  REAL8 sum = 0;
502  size_t isx, isy; // first non-zero spline
503  size_t iex, iey; // last non-zero spline
504  // Evaluate all potentially nonzero cubic B-spline basis functions for positions (eta,chi) and stores them in the vectors Bx4, By4.
505  // Since the B-splines are of compact support we only need to store a small number of basis functions
506  // to avoid computing terms that would be zero anyway.
507  // https://www.gnu.org/software/gsl/manual/html_node/Overview-of-B_002dsplines.html#Overview-of-B_002dsplines
508  gsl_bspline_eval_nonzero(eta, Bx4, &isx, &iex, bwx);
509  gsl_bspline_eval_nonzero(chi, By4, &isy, &iey, bwy);
510 
511  // Now compute coefficient at desired parameters (eta,chi) from C(eta,chi) = c_ij * Beta_i * Bchi_j
512  // summing over indices i,j where the B-splines are nonzero.
513  for (int i=0; i<4; i++)
514  for (int j=0; j<4; j++)
515  sum += gsl_matrix_get(&c, isx + i, isy + j) * gsl_vector_get(Bx4, i) * gsl_vector_get(By4, j);
516 
517  gsl_vector_free(Bx4);
518  gsl_vector_free(By4);
519 
520  return sum;
521 }
522 
523 // Returns fitting coefficients for cubic y = c[0] + c[1]*x + c[2]*x**2 + c[3]*x**3
524 static gsl_vector *Fit_cubic(const gsl_vector *xi, const gsl_vector *yi) {
525  const int n = xi->size; // how many data points are we fitting
526  const int p = 4; // order of fitting polynomial
527 
528  gsl_matrix *X = gsl_matrix_alloc(n, p); // design matrix
529  gsl_vector *y = gsl_vector_alloc(n); // data vector
530  gsl_vector *c = gsl_vector_alloc(p); // coefficient vector
531  gsl_matrix *cov = gsl_matrix_alloc(p, p);
532  double chisq;
533 
534  for (int i=0; i < n; i++) {
535  double xval = gsl_vector_get(xi, i);
536  double xval2 = xval*xval;
537  double xval3 = xval2*xval;
538  gsl_matrix_set(X, i, 0, 1.0);
539  gsl_matrix_set(X, i, 1, xval);
540  gsl_matrix_set(X, i, 2, xval2);
541  gsl_matrix_set(X, i, 3, xval3);
542 
543  double yval = gsl_vector_get(yi, i);
544  gsl_vector_set (y, i, yval);
545  }
546 
547  gsl_multifit_linear_workspace *work = gsl_multifit_linear_alloc(n, p);
548  gsl_multifit_linear(X, y, c, cov, &chisq, work); // perform linear least-squares fit
549 
550  // clean up
551  gsl_multifit_linear_free(work);
552  gsl_matrix_free(X);
553  gsl_matrix_free(cov);
554  gsl_vector_free(y);
555 
556  return c;
557 }
558 
559 // This function determines whether x and y are approximately equal to a relative accuracy epsilon.
560 // Note that x and y are compared to relative accuracy, so this function is not suitable for testing whether a value is approximately zero.
561 static bool approximately_equal(REAL8 x, REAL8 y, REAL8 epsilon) {
562  return !gsl_fcmp(x, y, epsilon);
563 }
564 
565 // If x and X are approximately equal to relative accuracy epsilon then set x = X.
566 // If X = 0 then use an absolute comparison.
567 static void nudge(REAL8 *x, REAL8 X, REAL8 epsilon) {
568  if (X != 0.0) {
569  if (approximately_equal(*x, X, epsilon)) {
570  XLAL_PRINT_INFO("Nudging value %.15g to %.15g\n", *x, X);
571  *x = X;
572  }
573  }
574  else {
575  if (fabs(*x - X) < epsilon)
576  *x = X;
577  }
578 }
579 
580 /* compute ringdown frequency for (2,2) mode from total mass and mass ratio */
582  const double Mtot_sec,
583  const double q,
584  const double chi1,
585  const double chi2,
586  Approximant apx
587 )
588 {
589  double Mtot_SI = Mtot_sec / LAL_MTSUN_SI * LAL_MSUN_SI;
590  double m1_SI = Mtot_SI * q / (1. + q);
591  double m2_SI = Mtot_SI * 1. / (1. + q);
592  return XLALSimInspiralGetFinalFreq(m1_SI, m2_SI, 0, 0, chi1, 0, 0, chi2, apx) * Mtot_sec;
593 }
594 
595 /* compute ringdown frequency for (2,2) mode from total mass and eta */
597  const double Mtot_sec,
598  const double eta,
599  const double chi1,
600  const double chi2,
601  Approximant apx
602 )
603 {
604  double q = (1. + sqrt(1. - 4. * eta) - 2. * eta) / (2. * eta);
605  return SEOBNRROM_Ringdown_Mf_From_Mtot_q(Mtot_sec, q, chi1, chi2, apx);
606 }
607 
608 /* SEOBNRv4HM_ROM functions */
609 
610 
611 // Helper function to concatenate strings
612 char* concatenate_strings(int count, ...)
613 {
614  va_list ap;
615  int i;
616 
617  // Find required length to store merged string
618  int len = 1; // room for NULL
619  va_start(ap, count);
620  for(i=0 ; i<count ; i++)
621  len += strlen(va_arg(ap, char*));
622  va_end(ap);
623 
624  // Allocate memory to concat strings
625  char *merged = XLALCalloc(sizeof(char),len);
626  int null_pos = 0;
627 
628  // Actually concatenate strings
629  va_start(ap, count);
630  for(i=0 ; i<count ; i++)
631  {
632  char *s = va_arg(ap, char*);
633  strcpy(merged+null_pos, s);
634  null_pos += strlen(s);
635  }
636  va_end(ap);
637 
638  return merged;
639 }
640 
641 /* Sigmoid function for hybridization */
643 {
644  REAL8 exp_value;
645  REAL8 return_value;
646 
647  /*** Exponential calculation ***/
648  exp_value = exp(-x);
649 
650  /*** Final sigmoid value ***/
651  return_value = 1 / (1 + exp_value);
652 
653  return return_value;
654 }
655 
656 // Compute activation function in a window [freq_1, freq_2]
657 UINT4 blend(gsl_vector * freqs, gsl_vector * out_fun, REAL8 freq_1, REAL8 freq_2){
658  for(unsigned int i = 0; i < freqs->size; i++){
659  if(freqs->data[i] <= freq_1){
660  out_fun->data[i] = 0.;
661  }
662  else if((freqs->data[i]>freq_1) && (freqs->data[i]<freq_2)){
663  out_fun->data[i] = sigmoid(- (freq_2 - freq_1)/(freqs->data[i]-freq_1) - (freq_2 - freq_1)/(freqs->data[i]-freq_2));
664  }
665  else{
666  out_fun->data[i] = 1.;
667  }
668  }
669  return XLAL_SUCCESS;
670 }
671 
672 // Function to compute the indices associated to [freq_1] in two arrays
673 UINT4 compute_i_max_LF_i_min_HF(INT8 * i_max_LF, INT8 * i_min_HF,gsl_vector * freqs_in_1,gsl_vector * freqs_in_2, REAL8 freq_1){
674 
675  for(unsigned int i = 0; i < freqs_in_1->size; i++){
676  if(freqs_in_1->data[i]<freq_1){
677  *i_max_LF = i;
678  }
679  }
680  for(unsigned int i = freqs_in_2->size -1; i > 0; i--){
681  if(freqs_in_2->data[i]>=freq_1){
682  *i_min_HF = i;
683  }
684  }
685 return XLAL_SUCCESS;
686 }
687 
688 // Function to compute the index associated to [freq_1] in an array
689 UINT8 compute_i_at_f(gsl_vector * freq_array, REAL8 freq){
690  UINT8 index = 0;
691  REAL8 diff = fabs(freq-freq_array->data[index]);
692  for(unsigned int i = 1; i < freq_array->size; i++){
693  if(fabs(freq-freq_array->data[i])< diff){
694  diff = fabs(freq-freq_array->data[i]);
695  index = i;
696  }
697  }
698  return index;
699 }
700 
701 /* Function to blend LF and HF ROM functions in a window [freq_1, freq_2] */
702 UINT4 blend_functions(gsl_vector * freqs_out, gsl_vector * out_fun, gsl_vector * freq_in_1, gsl_vector * fun_in_1, gsl_vector * freq_in_2, gsl_vector * fun_in_2, REAL8 freq_1, REAL8 freq_2){
703 
704  gsl_vector *bld_2 = gsl_vector_calloc(out_fun->size);
705 
706  /* Generate the window function */
707  UNUSED UINT4 ret = blend(freqs_out, bld_2,freq_1,freq_2);
708 
709  gsl_interp_accel *acc = gsl_interp_accel_alloc ();
710  gsl_spline *spline = gsl_spline_alloc (gsl_interp_cspline, freq_in_1->size);
711  gsl_spline_init (spline, freq_in_1->data, fun_in_1->data, freq_in_1->size);
712 
713  unsigned int i = 0;
714  REAL8 inter_func;
715  /* Build the contribution to out_fun from fun_in_1 in the range [f_ini, freq_2] */
716  /* where f_ini is the starting frequency of the array freq_in_1 */
717  /* for freq > freq_2 the contribution of fun_in_1 to out_fun is null since 1 - bld_2 = 0 there*/
718  /* for freq < freq_1, bld_2 = 0, so I could have another easier while in the range [freq_1,freq_2]*/
719 
720  while(freqs_out->data[i]<=freq_2){
721  /* Interpolate the original function on the new grid */
722  inter_func = gsl_spline_eval (spline, freqs_out->data[i], acc);
723  /* Multiply the original function by the window function */
724  out_fun->data[i] = inter_func*(1.-bld_2->data[i]);
725  i++;
726  }
727  gsl_spline_free (spline);
728 
729  /* Build the contribution to out_fun from fun_in_2 in the range [freq_2, f_end] */
730  /* where f_end is the ending frequency of the array freq_in_2 */
731  /* for freq > freq_2, bld_2 = 1*/
732  spline = gsl_spline_alloc (gsl_interp_cspline, freq_in_2->size);
733  gsl_spline_init (spline, freq_in_2->data, fun_in_2->data, freq_in_2->size);
734  i = freqs_out->size-1;
735  while(freqs_out->data[i]>freq_2){
736  inter_func = gsl_spline_eval (spline, freqs_out->data[i], acc);
737  out_fun->data[i] = inter_func;
738  i--;
739  }
740 
741  /* Build the contribution to out_fun from fun_in_2 in the range [freq_1, freq_2] */
742  /* where f_end is the ending frequency of the array freq_in_2 */
743  while((freqs_out->data[i]>=freq_1)&&(freqs_out->data[i]<=freq_2)){
744  inter_func = gsl_spline_eval (spline, freqs_out->data[i], acc);
745  out_fun->data[i] += inter_func*bld_2->data[i];
746  /* Note that the += is important here */
747  i--;
748  }
749 
750  /* Cleanup */
751  gsl_vector_free(bld_2);
752  gsl_spline_free (spline);
753  gsl_interp_accel_free(acc);
754 
755  return XLAL_SUCCESS;
756 }
757 
758 // Function to align two phases in a window [f_align_start,f_align_end]
759 // Output phase shift, time shift from the linear fit of phi2 - phi1
760 // Convention for alignment quantities:
761 // phase_2 ~= phase_1 + Deltaphi + 2pi*f*Deltat
762 UINT4 align_wfs_window(gsl_vector* f_array_1, gsl_vector* f_array_2, gsl_vector* phase_1, gsl_vector* phase_2, REAL8* Deltat, REAL8* Deltaphi, REAL8 f_align_start, REAL8 f_align_end){
763 
764  /* Check frequency range */
765  if((f_align_start<f_array_1->data[0]) || (f_align_start<f_array_2->data[0]) || (f_align_end>f_array_1->data[f_array_1->size-1]) || (f_align_end>f_array_2->data[f_array_2->size-1])) {
766  XLAL_ERROR(XLAL_EINVAL, "Incompatible frequency ranges.");
767  }
768  /* Number of points to fit the phase difference */
769  /* arbitrary, suitable for linear fit */
770  UINT8 npt_fit = 10;
771  // Interpolate phase_1 phase on phase_2 frequency grid between [f_align_start,f_align_end] and compute phase difference
772  gsl_interp_accel *acc_1 = gsl_interp_accel_alloc();
773  gsl_spline *spline_1 = gsl_spline_alloc(gsl_interp_cspline, phase_1->size);
774  gsl_spline_init(spline_1, f_array_1->data, phase_1->data, phase_1->size);
775  gsl_interp_accel *acc_2 = gsl_interp_accel_alloc();
776  gsl_spline *spline_2 = gsl_spline_alloc(gsl_interp_cspline, phase_2->size);
777  gsl_spline_init(spline_2, f_array_2->data, phase_2->data, phase_2->size);
778  gsl_vector* delta_phi = gsl_vector_alloc(npt_fit);
779  gsl_vector* freq_delta_phi = gsl_vector_alloc(npt_fit);
780  // delta_phi is phi2-phi1
781  REAL8 f = 0.;
782  for(unsigned int i=0; i<freq_delta_phi->size; i++){
783  f = f_align_start + ((double) i)/(freq_delta_phi->size - 1) * (f_align_end-f_align_start);
784  freq_delta_phi->data[i] = f;
785  delta_phi->data[i] = gsl_spline_eval(spline_2, f, acc_2) - gsl_spline_eval(spline_1, f, acc_1);
786  }
787  REAL8 c0, c1, cov00, cov01, cov11, chisq;
788  gsl_fit_linear(freq_delta_phi->data, 1, delta_phi->data, 1, freq_delta_phi->size, &c0, &c1, &cov00, &cov01, &cov11, &chisq);
789  *Deltaphi = c0;
790  *Deltat = c1 / (2*LAL_PI);
791 
792  // Remove the linear fit from phase_1
793  for(unsigned int i = 0; i < f_array_1->size; i++){
794  phase_1->data[i] = phase_1->data[i] + (c1*f_array_1->data[i] + c0);
795  }
796  /* Cleanup */
797  gsl_vector_free(delta_phi);
798  gsl_vector_free(freq_delta_phi);
799  gsl_spline_free(spline_1);
800  gsl_interp_accel_free(acc_1);
801  gsl_spline_free(spline_2);
802  gsl_interp_accel_free(acc_2);
803 
804  return XLAL_SUCCESS;
805 
806 }
807 
808 // Useful debugging functions
809 UNUSED static void test_save_gsl_vector(const char filename[], gsl_vector *v);
810 UNUSED static void test_save_gsl_spline(const char filename[], gsl_spline *s);
811 UNUSED static void test_save_cmplx_freq_series(COMPLEX16FrequencySeries *mode, const char filename[], bool save_real_part);
812 
813 /********************* Definitions begin here ********************/
814 
815 UNUSED static void test_save_gsl_vector(const char filename[], gsl_vector *v) {
816  FILE *fp = fopen(filename, "w");
817  gsl_vector_fprintf(fp, v, "%g");
818  fclose(fp);
819 }
820 
821 UNUSED static void test_save_gsl_spline(const char filename[], gsl_spline *s) {
822  FILE *fp = fopen(filename, "w");
823  for (size_t i=0; i < s->size; i++) {
824  fprintf(fp, "%g\t%g\n", s->x[i], s->y[i]);
825  }
826  fclose(fp);
827 }
828 
829 UNUSED static void test_save_cmplx_freq_series(
831  const char filename[],
832  bool save_real_part)
833 {
834  // Save either the real or imaginary part of a COMPLEX16FrequencySeries to a file.
835  gsl_vector *v = gsl_vector_alloc(mode->data->length);
836  double (*part_fun_ptr)(double complex);
837  if (save_real_part)
838  part_fun_ptr = creal;
839  else
840  part_fun_ptr = cimag;
841  for (unsigned int i=0; i<mode->data->length; i++)
842  gsl_vector_set(v, i, part_fun_ptr(mode->data->data[i]));
844  gsl_vector_free(v);
845 }
846 
847 // Function to align two phases with a given 22-mode constant and slope
848 // using the window [f_align_start,f_align_end] to determine an additional pi
849 // (in general there is a pi ambiguity in m/2*Deltaphi_22)
850 // Convention for alignment quantities:
851 // phase2_22 ~= phase1_22 + Deltaphi22_align + 2pi*f*Deltat22_align
852 UINT4 align_wfs_window_from_22(gsl_vector* f_array_1, gsl_vector* f_array_2, gsl_vector* phase_1, gsl_vector* phase_2, REAL8 f_align_start, REAL8 f_align_end, REAL8 Deltat22, REAL8 Deltaphi22, INT4 modeM){
853 
854  /* Check frequency range */
855  if((f_align_start<f_array_1->data[0]) || (f_align_start<f_array_2->data[0]) || (f_align_end>f_array_1->data[f_array_1->size-1]) || (f_align_end>f_array_2->data[f_array_2->size-1])) {
856  XLAL_ERROR(XLAL_EINVAL, "Incompatible frequency ranges.");
857  }
858  /* Number of points to fit the phase difference */
859  /* arbitrary, suitable for linear fit */
860  UINT8 npt_fit = 10;
861  // Interpolate phase_1 phase on phase_2 frequency grid between [f_align_start,f_align_end] and compute phase difference
862  gsl_interp_accel *acc_1 = gsl_interp_accel_alloc();
863  gsl_spline *spline_1 = gsl_spline_alloc(gsl_interp_cspline, phase_1->size);
864  gsl_spline_init(spline_1, f_array_1->data, phase_1->data, phase_1->size);
865  gsl_interp_accel *acc_2 = gsl_interp_accel_alloc();
866  gsl_spline *spline_2 = gsl_spline_alloc(gsl_interp_cspline, phase_2->size);
867  gsl_spline_init(spline_2, f_array_2->data, phase_2->data, phase_2->size);
868  gsl_vector* delta_phi = gsl_vector_alloc(npt_fit);
869  gsl_vector* freq_delta_phi = gsl_vector_alloc(npt_fit);
870  // delta_phi is phi2-phi1, taking into account the constant and linear term from alignment to be added
871  REAL8 f = 0.;
872  for(unsigned int i=0; i<freq_delta_phi->size; i++){
873  f = f_align_start + ((double) i)/(freq_delta_phi->size - 1) * (f_align_end-f_align_start);
874  delta_phi->data[i] = gsl_spline_eval(spline_2, f, acc_2) - gsl_spline_eval(spline_1, f, acc_1) - (2*LAL_PI*Deltat22*f + modeM/2.*Deltaphi22);
875  }
876 
877  // Determine a possible additional pi-shift (pi-ambiguity in m/2*Deltaphi22)
878  REAL8 av_phase_diff = 0.;
879  for(unsigned int i = 0; i < freq_delta_phi->size; i++){
880  av_phase_diff += delta_phi->data[i];
881  }
882  av_phase_diff = av_phase_diff / (delta_phi->size);
883 
884  // Closest multiple of pi to eliminate the residual phase diff
885  REAL8 pishift = floor((av_phase_diff + LAL_PI/2) / LAL_PI) * LAL_PI;
886 
887  // Remove the scaled linear fit and pi shift from phase_1
888  for(unsigned int i = 0; i < f_array_1->size; i++){
889  phase_1->data[i] = phase_1->data[i] + (2*LAL_PI*Deltat22*f_array_1->data[i] + modeM/2.*Deltaphi22 + pishift);
890  }
891 
892  /* Cleanup */
893  gsl_vector_free(delta_phi);
894  gsl_vector_free(freq_delta_phi);
895  gsl_spline_free(spline_1);
896  gsl_interp_accel_free(acc_1);
897  gsl_spline_free(spline_2);
898  gsl_interp_accel_free(acc_2);
899 
900  return XLAL_SUCCESS;
901 
902 }
903 
904 // Function to compute the QNM frequency
906  // Total mass M is not important here, we return the QNM frequencies in geometric units
907  REAL8 M = 100.;
908  REAL8 Ms = M * LAL_MTSUN_SI;
909  REAL8 m1 = M * q/(1+q);
910  REAL8 m2 = M * 1/(1+q);
911  Approximant SpinAlignedEOBapproximant = SEOBNRv4;
912  COMPLEX16Vector modefreqVec;
913  COMPLEX16 modeFreq;
914  modefreqVec.length = 1;
915  modefreqVec.data = &modeFreq;
916  REAL8 spin1[3] = {0., 0., chi1z};
917  REAL8 spin2[3] = {0., 0., chi2z};
918  // XLALSimIMREOBGenerateQNMFreqV2 is returning QNM frequencies in SI units, we multiply by Ms to convert it in geometric units
919  UNUSED UINT4 ret = XLALSimIMREOBGenerateQNMFreqV2(&modefreqVec, m1, m2, spin1, spin2, l, m, 1, SpinAlignedEOBapproximant);
920  return Ms * creal(modefreqVec.data[0]);
921 }
922 
923 // Function to compute the SEOBNRv5 QNM frequency
925  // Total mass M is not important here, we return the QNM frequencies in geometric units
926  REAL8 M = 100.;
927  REAL8 Ms = M * LAL_MTSUN_SI;
928  REAL8 m1 = M * q/(1+q);
929  REAL8 m2 = M * 1/(1+q);
930  Approximant SpinAlignedEOBapproximant = SEOBNRv5_ROM; // SEOBNRv5 uses different final state fits compared to SEOBNRv4
931  COMPLEX16Vector modefreqVec;
932  COMPLEX16 modeFreq;
933  modefreqVec.length = 1;
934  modefreqVec.data = &modeFreq;
935  REAL8 spin1[3] = {0., 0., chi1z};
936  REAL8 spin2[3] = {0., 0., chi2z};
937  // XLALSimIMREOBGenerateQNMFreqV5 is returning QNM frequencies in SI units, we multiply by Ms to convert it in geometric units
938  UNUSED UINT4 ret = XLALSimIMREOBGenerateQNMFreqV5(&modefreqVec, m1, m2, spin1, spin2, l, m, 1, SpinAlignedEOBapproximant);
939  return Ms * creal(modefreqVec.data[0]);
940 }
941 
942 /* Function to unwrap phases mod 2pi - acts on a REAL8Vector representing the phase */
943 /* FIXME: for long vectors there are small differences with the numpy unwrap function - to be checked */
945  gsl_vector* phaseout, /* Output: unwrapped phase vector, already allocated - can be the same as phasein, in which case unwrapping is done in place */
946  gsl_vector* phasein) /* Input: phase vector */
947 {
948  int N = phasein->size;
949  double* p = phasein->data;
950  double* pmod = (double*) malloc(sizeof(double) * N);
951  int* jumps = (int*) malloc(sizeof(int) * N);
952  int* cumul = (int*) malloc(sizeof(int) * N);
953 
954  /* Compute phase mod 2pi (shifted to be between -pi and pi) */
955  for(int i=0; i<N; i++) {
956  pmod[i] = p[i] - floor((p[i] + LAL_PI) / (2*LAL_PI))*(2*LAL_PI);
957  }
958 
959  /* Identify jumps */
960  jumps[0] = 0;
961  double d = 0.;
962  for(int i=1; i<N; i++) {
963  d = pmod[i] - pmod[i-1];
964  if(d<-LAL_PI) jumps[i] = 1;
965  else if(d>LAL_PI) jumps[i] = -1;
966  else jumps[i] = 0;
967  }
968 
969  /* Cumulative of the jump sequence */
970  int c = 0;
971  cumul[0] = 0;
972  for(int i=1; i<N; i++) {
973  c += jumps[i];
974  cumul[i] = c;
975  }
976 
977  /* Correct mod 2pi phase series by the number of 2pi factor given by the cumulative of the jumps */
978  double* pout = phaseout->data;
979  for(int i=0; i<N; i++) {
980  pout[i] = pmod[i] + 2*LAL_PI*cumul[i];
981  }
982 
983  /* Cleanup */
984  free(pmod);
985  free(jumps);
986  free(cumul);
987 
988  return XLAL_SUCCESS;
989 }
struct tagLALH5File LALH5File
struct tagLALH5Dataset LALH5Dataset
#define LALFree(p)
INT4 XLALSimIMREOBGenerateQNMFreqV5(COMPLEX16Vector *modefreqs, const REAL8 mass1, const REAL8 mass2, const REAL8 spin1[3], const REAL8 spin2[3], UINT4 l, INT4 m, UINT4 nmodes, Approximant approximant)
These functions generate the quasinormal mode frequencies for a black hole ringdown,...
const double c1
const double c0
static UNUSED void test_save_gsl_vector(const char filename[], gsl_vector *v)
static UNUSED UINT8 compute_i_at_f(gsl_vector *freq_array, REAL8 freq)
static UNUSED gsl_vector * Fit_cubic(const gsl_vector *xi, const gsl_vector *yi)
static UNUSED void nudge(REAL8 *x, REAL8 X, REAL8 epsilon)
static UNUSED UINT4 align_wfs_window_from_22(gsl_vector *f_array_1, gsl_vector *f_array_2, gsl_vector *phase_1, gsl_vector *phase_2, REAL8 f_align_start, REAL8 f_align_end, REAL8 Deltat22, REAL8 Deltaphi22, INT4 modeM)
static UNUSED REAL8 Get_omegaQNM_SEOBNRv5(REAL8 q, REAL8 chi1z, REAL8 chi2z, UINT4 l, UINT4 m)
static UNUSED double SEOBNRROM_Ringdown_Mf_From_Mtot_q(const double Mtot_sec, const double q, const double chi1, const double chi2, Approximant apx)
static UNUSED void test_save_gsl_spline(const char filename[], gsl_spline *s)
static UNUSED UINT4 compute_i_max_LF_i_min_HF(INT8 *i_max_LF, INT8 *i_min_LF, gsl_vector *freqs_in_1, gsl_vector *freqs_in_2, REAL8 freq_1)
static UNUSED REAL8 Interpolate_Coefficent_Tensor(gsl_vector *v, REAL8 eta, REAL8 chi1, REAL8 chi2, int ncy, int ncz, gsl_bspline_workspace *bwx, gsl_bspline_workspace *bwy, gsl_bspline_workspace *bwz)
static UNUSED REAL8 Get_omegaQNM_SEOBNRv4(REAL8 q, REAL8 chi1z, REAL8 chi2z, UINT4 l, UINT4 m)
static UNUSED UINT4 unwrap_phase(gsl_vector *phaseout, gsl_vector *phasein)
static UNUSED int read_vector(const char dir[], const char fname[], gsl_vector *v)
static UNUSED void test_save_cmplx_freq_series(COMPLEX16FrequencySeries *mode, const char filename[], bool save_real_part)
static UNUSED UINT4 align_wfs_window(gsl_vector *f_array_1, gsl_vector *f_array_2, gsl_vector *phase_1, gsl_vector *phase_2, REAL8 *Deltat, REAL8 *Deltaphi, REAL8 f_align_start, REAL8 f_align_end)
static UNUSED UINT4 blend(gsl_vector *freqs, gsl_vector *out_fun, REAL8 freq_1, REAL8 freq_2)
static UNUSED double SEOBNRROM_Ringdown_Mf_From_Mtot_Eta(const double Mtot_sec, const double eta, const double chi1, const double chi2, Approximant apx)
static UNUSED char * concatenate_strings(int count,...)
static UNUSED REAL8 sigmoid(REAL8 x)
static UNUSED UINT4 blend_functions(gsl_vector *freqs_out, gsl_vector *out_fun, gsl_vector *freq_in_1, gsl_vector *fun_in_1, gsl_vector *freq_in_2, gsl_vector *fun_in_2, REAL8 freq_1, REAL8 freq_2)
static UNUSED int read_matrix(const char dir[], const char fname[], gsl_matrix *m)
static UNUSED REAL8 Interpolate_Coefficent_Matrix(gsl_vector *v, REAL8 eta, REAL8 chi, int ncx, int ncy, gsl_bspline_workspace *bwx, gsl_bspline_workspace *bwy)
static UNUSED bool approximately_equal(REAL8 x, REAL8 y, REAL8 epsilon)
double XLALSimInspiralGetFinalFreq(REAL8 m1, REAL8 m2, const REAL8 S1x, const REAL8 S1y, const REAL8 S1z, const REAL8 S2x, const REAL8 S2y, const REAL8 S2z, Approximant approximant)
Function that gives the default ending frequencies of the given approximant.
static vector d(const double L_norm, const double J_norm, const vector roots)
Internal function that returns the coefficients "d_0", "d_2" and "d_4" from 1703.03967 corresponding ...
#define c
const char * name
static REAL8 sum(REAL8 *arr1, REAL8 *arr2, int k)
#define fprintf
int s
Definition: bh_qnmode.c:137
int l
Definition: bh_qnmode.c:135
REAL8 M
Definition: bh_qnmode.c:133
double i
Definition: bh_ringdown.c:118
sigmaKerr data[0]
void XLALH5DatasetFree(LALH5Dataset UNUSED *dset)
UINT4Vector * XLALH5DatasetQueryDims(LALH5Dataset UNUSED *dset)
int XLALH5AttributeQueryStringValue(char UNUSED *value, size_t UNUSED size, const LALH5Generic UNUSED object, const char UNUSED *key)
LALTYPECODE XLALH5DatasetQueryType(LALH5Dataset UNUSED *dset)
int XLALH5AttributeQueryScalarValue(void UNUSED *value, const LALH5Generic UNUSED object, const char UNUSED *key)
LALH5Dataset * XLALH5DatasetRead(LALH5File UNUSED *file, const char UNUSED *name)
int XLALH5DatasetQueryData(void UNUSED *data, LALH5Dataset UNUSED *dset)
int XLALH5FileQueryStringAttributeValue(char UNUSED *value, size_t UNUSED size, LALH5File UNUSED *file, const char UNUSED *key)
#define LAL_MSUN_SI
#define LAL_PI
#define LAL_MTSUN_SI
uint64_t UINT8
double complex COMPLEX16
double REAL8
int64_t INT8
uint32_t UINT4
int32_t INT4
LAL_I8_TYPE_CODE
LAL_D_TYPE_CODE
void * XLALCalloc(size_t m, size_t n)
void * XLALMalloc(size_t n)
void XLALFree(void *p)
INT4 XLALSimIMREOBGenerateQNMFreqV2(COMPLEX16Vector *modefreqs, const REAL8 mass1, const REAL8 mass2, const REAL8 spin1[3], const REAL8 spin2[3], UINT4 l, INT4 m, UINT4 nmodes, Approximant approximant)
These functions generate the quasinormal mode frequencies for a black hole ringdown.
Approximant
Enum that specifies the PN approximant to be used in computing the waveform.
@ SEOBNRv4
Spin nonprecessing EOBNR model v4.
@ SEOBNRv5_ROM
Time domain, precessing phenomenological IMR waveform model with subdominant modes ([arXiv: 20XY....
static const INT4 m
static const INT4 q
void XLALDestroyUINT4Vector(UINT4Vector *vector)
#define XLAL_PRINT_INFO(...)
int int int XLALPrintInfo(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_ERROR(...)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_ETYPE
XLAL_EIO
XLAL_EDIMS
XLAL_EINVAL
list x
list p
list y
path
filename
int N
const char * file_name
Definition: sgwb.c:110
COMPLEX16Sequence * data
COMPLEX16 * data
UINT4 * data
FILE * fp
LALH5File * file