25#define UNUSED __attribute__ ((unused))
39#include <gsl/gsl_errno.h>
40#include <gsl/gsl_bspline.h>
41#include <gsl/gsl_blas.h>
42#include <gsl/gsl_min.h>
43#include <gsl/gsl_spline.h>
44#include <gsl/gsl_complex_math.h>
46#include <lal/SeqFactories.h>
47#include <lal/LALConstants.h>
48#include <lal/XLALError.h>
49#include <lal/FrequencySeries.h>
51#include <lal/StringInput.h>
52#include <lal/Sequence.h>
53#include <lal/LALStdio.h>
54#include <lal/FileIO.h>
55#include <lal/SphericalHarmonics.h>
56#include <lal/LALSimInspiral.h>
57#include <lal/LALSimSphHarmMode.h>
58#include <lal/LALSimIMR.h>
60#ifdef LAL_HDF5_ENABLED
61#include <lal/H5FileIO.h>
68#include <lal/LALConfig.h>
69#ifdef LAL_PTHREAD_LOCK
74#ifdef LAL_PTHREAD_LOCK
75UNUSED
static pthread_once_t NRSur7dq2_is_initialized = PTHREAD_ONCE_INIT;
78#ifdef LAL_PTHREAD_LOCK
79UNUSED
static pthread_once_t NRSur7dq4_is_initialized = PTHREAD_ONCE_INIT;
155#ifdef LAL_HDF5_ENABLED
160static void NRSur7dq2_Init_LALDATA(
void) {
166 char *dir = dirname(
path);
184#ifdef LAL_HDF5_ENABLED
189static void NRSur7dq4_Init_LALDATA(
void) {
196 "Unable to resolve data file '%s' in $LAL_DATA_PATH.\n"
197 "Note: LALSuite versions >= 7.25 require data files that are publicly available at:\n"
198 "https://git.ligo.org/waveforms/software/lalsuite-waveform-data\n"
199 "and on Zenodo at: https://zenodo.org/records/14999310.\n"
200 "For earlier LALSuite versions, use the files in lalsuite-extra, available at:\n"
201 "https://git.ligo.org/lscsoft/lalsuite-extra\n",
204 char *dir = dirname(path);
215 "CANONICAL_FILE_BASENAME");
229static int PrecessingNRSur_Init(
232 UINT4 PrecessingNRSurVersion
238 XLALPrintError(
"You tried to setup a NRSurrogate model that was already initialized. Ignoring.\n");
243 gsl_vector *t_ds_with_halves = NULL;
244 ReadHDF5RealVectorDataset(
file,
"t_ds", &t_ds_with_halves);
246 gsl_vector *t_ds = gsl_vector_alloc(t_ds_with_halves->size - 3);
247 gsl_vector *t_ds_half_times = gsl_vector_alloc(3);
248 for (
i=0;
i < 3;
i++) {
249 gsl_vector_set(t_ds,
i, gsl_vector_get(t_ds_with_halves, 2*
i));
250 gsl_vector_set(t_ds_half_times,
i, gsl_vector_get(t_ds_with_halves, 2*
i + 1));
252 for (
i=3;
i < t_ds->size;
i++) {
253 gsl_vector_set(t_ds,
i, gsl_vector_get(t_ds_with_halves,
i+3));
255 gsl_vector_free(t_ds_with_halves);
257 data->t_ds_half_times = t_ds_half_times;
266 for (
i=0;
i < (t_ds->size);
i++) ds_node_data[
i] = NULL;
267 for (
i=0;
i < 3;
i++) ds_half_node_data[
i] = NULL;
271 for (
i=0;
i < (t_ds->size);
i++) {
272 if (
i < 3) {j = 2*
i;}
else {j =
i+3;}
273 snprintf(sub_name, 20,
"ds_node_%d", j);
275 PrecessingNRSur_LoadDynamicsNode(ds_node_data, sub,
i, PrecessingNRSurVersion);
278 snprintf(sub_name, 20,
"ds_node_%d", j+1);
280 PrecessingNRSur_LoadDynamicsNode(ds_half_node_data, sub,
i, PrecessingNRSurVersion);
284 data->ds_node_data = ds_node_data;
285 data->ds_half_node_data = ds_half_node_data;
288 gsl_vector *t_coorb = NULL;
289 ReadHDF5RealVectorDataset(
file,
"t_coorb", &t_coorb);
291 data->t_coorb = t_coorb;
295 for (
int ell_idx=0; ell_idx <
NRSUR_LMAX-1; ell_idx++) {
296 PrecessingNRSur_LoadCoorbitalEllModes(coorbital_mode_data,
file, ell_idx);
298 data->coorbital_mode_data = coorbital_mode_data;
309static void PrecessingNRSur_LoadFitData(
316 const size_t str_size = 30;
318 UNUSED
size_t nwritten;
320 nwritten = snprintf(tmp_name, str_size,
"%s_coefs",
name);
322 (*fit_data)->coefs = NULL;
324 ReadHDF5RealVectorDataset(sub, tmp_name, &((*fit_data)->coefs));
326 nwritten = snprintf(tmp_name, str_size,
"%s_bfOrders",
name);
328 (*fit_data)->basisFunctionOrders = NULL;
329 ReadHDF5LongMatrixDataset(sub, tmp_name,
330 &((*fit_data)->basisFunctionOrders));
332 (*fit_data)->n_coefs = (*fit_data)->coefs->size;
340static void NRSur7dq4_LoadVectorFitData(
346 const size_t str_size = 20;
348 UNUSED
size_t nwritten;
351 (*vector_fit_data)->vec_dim = size;
354 for (
size_t i=0;
i<size;
i++) {
355 nwritten = snprintf(tmp_name, str_size,
"%s_%zu",
name,
i);
358 PrecessingNRSur_LoadFitData(&fit_data, sub, tmp_name);
359 (*vector_fit_data)->fit_data[
i] = fit_data;
367static void PrecessingNRSur_LoadDynamicsNode(
371 UINT4 PrecessingNRSurVersion
373 ds_node_data[
i] =
XLALMalloc(
sizeof(*ds_node_data[
i]) );
378 PrecessingNRSur_LoadFitData(&omega_data, sub,
"omega");
382 if (PrecessingNRSurVersion == 0){
386 omega_copr_data->
coefs = NULL;
389 ReadHDF5RealVectorDataset(sub,
"omega_orb_coefs", &(omega_copr_data->
coefs));
390 ReadHDF5LongMatrixDataset(sub,
"omega_orb_bfOrders", &(omega_copr_data->
basisFunctionOrders));
391 ReadHDF5LongVectorDataset(sub,
"omega_orb_bVecIndices", &(omega_copr_data->
componentIndices));
392 omega_copr_data->
n_coefs = omega_copr_data->
coefs->size;
398 chiA_dot_data->
coefs = NULL;
401 ReadHDF5RealVectorDataset(sub,
"chiA_coefs", &(chiA_dot_data->
coefs));
403 ReadHDF5LongVectorDataset(sub,
"chiA_bVecIndices", &(chiA_dot_data->
componentIndices));
411 chiB_dot_data->
coefs = NULL;
420 n = dimLength->
data[0];
424 ReadHDF5RealVectorDataset(sub,
"chiB_coefs", &(chiB_dot_data->
coefs));
426 ReadHDF5LongVectorDataset(sub,
"chiB_bVecIndices", &(chiB_dot_data->
componentIndices));
434 }
else if (PrecessingNRSurVersion == 1) {
437 NRSur7dq4_LoadVectorFitData(&omega_copr_data, sub,
"omega_orb", 2);
442 NRSur7dq4_LoadVectorFitData(&chiA_dot_data, sub,
"chiA", 3);
447 NRSur7dq4_LoadVectorFitData(&chiB_dot_data, sub,
"chiB", 3);
456static void PrecessingNRSur_LoadCoorbitalEllModes(
462 mode_data->
ell =
i+2;
469 snprintf(sub_name, str_size,
"hCoorb_%d_0_real",
i+2);
471 PrecessingNRSur_LoadWaveformDataPiece(sub, &(mode_data->
m0_real_data),
false);
474 snprintf(sub_name, str_size,
"hCoorb_%d_0_imag",
i+2);
476 PrecessingNRSur_LoadWaveformDataPiece(sub, &(mode_data->
m0_imag_data),
false);
496 for (
int m=1;
m<=(
i+2);
m++) {
497 snprintf(sub_name, str_size,
"hCoorb_%d_%d_Re+",
i+2,
m);
499 PrecessingNRSur_LoadWaveformDataPiece(sub, &(mode_data->
X_real_plus_data[
m-1]),
false);
500 snprintf(sub_name, str_size,
"hCoorb_%d_%d_Re-",
i+2,
m);
502 PrecessingNRSur_LoadWaveformDataPiece(sub, &(mode_data->
X_real_minus_data[
m-1]),
true);
503 snprintf(sub_name, str_size,
"hCoorb_%d_%d_Im+",
i+2,
m);
505 PrecessingNRSur_LoadWaveformDataPiece(sub, &(mode_data->
X_imag_plus_data[
m-1]),
true);
506 snprintf(sub_name, str_size,
"hCoorb_%d_%d_Im-",
i+2,
m);
508 PrecessingNRSur_LoadWaveformDataPiece(sub, &(mode_data->
X_imag_minus_data[
m-1]),
false);
511 coorbital_mode_data[
i] = mode_data;
518static void PrecessingNRSur_LoadWaveformDataPiece(
525 gsl_matrix *EI_basis = NULL;
526 ReadHDF5RealMatrixDataset(sub,
"EIBasis", &EI_basis);
528 gsl_matrix_scale(EI_basis, -1);
530 (*data)->empirical_interpolant_basis = EI_basis;
532 gsl_vector_long *node_indices = NULL;
533 ReadHDF5LongVectorDataset(sub,
"nodeIndices", &node_indices);
534 (*data)->empirical_node_indices = node_indices;
536 int n_nodes = (*data)->empirical_node_indices->size;
537 (*data)->n_nodes = n_nodes;
543 for (
int i=0;
i<n_nodes;
i++) {
545 node_data->
coefs = NULL;
547 snprintf(sub_name, str_size,
"coefs_%d",
i);
548 ReadHDF5RealVectorDataset(nodeModelers, sub_name, &(node_data->
coefs));
549 snprintf(sub_name, str_size,
"bfOrders_%d",
i);
552 (*data)->fit_data[
i] = node_data;
577 if (exponent == 0)
return 1.0;
579 while (exponent > 1) {
609 for (
i=0;
i<22;
i++) {
611 x_powers[
i] =
ipow(q_fit,
i/7);
618 for (
i=0;
i <
data->n_coefs;
i++) {
620 prod = x_powers[7 * gsl_matrix_long_get(
data->basisFunctionOrders,
i, 0)];
622 for (j=1; j<7; j++) {
623 prod *= x_powers[7 * gsl_matrix_long_get(
data->basisFunctionOrders,
i, j) + j];
625 res += gsl_vector_get(
data->coefs,
i) * prod;
646 for (
i=0;
i <
data->vec_dim;
i++) {
654 for (
i=0;
i<22;
i++) {
656 x_powers[
i] =
ipow(q_fit,
i/7);
663 for (
i=0;
i <
data->n_coefs;
i++) {
665 prod = x_powers[7 * gsl_matrix_long_get(
data->basisFunctionOrders,
i, 0)];
667 for (j=1; j<7; j++) {
668 prod *= x_powers[7 * gsl_matrix_long_get(
data->basisFunctionOrders,
i, j) + j];
670 res[gsl_vector_long_get(
data->componentIndices,
i)] += gsl_vector_get(
data->coefs,
i) * prod;
687 const REAL8 chi_wtAvg = (
q*chi1z+chi2z)/(1+
q);
688 REAL8 chiHat_val = (chi_wtAvg - 38.*eta/113.*(chi1z
689 + chi2z))/(1. - 76.*eta/113.);
690 REAL8 chi_a_val = (chi1z - chi2z)/2.;
691 *chiHat = chiHat_val;
717 fit_params[0] = log(
x[0]);
718 fit_params[1] =
x[1];
719 fit_params[2] =
x[2];
720 fit_params[3] = chiHat;
721 fit_params[4] =
x[4];
722 fit_params[5] =
x[5];
723 fit_params[6] = chi_a;
730 for (
i=0;
i<22;
i++) {
732 x_powers[
i] =
ipow(q_fit,
i/7);
734 x_powers[
i] =
ipow(fit_params[
i%7],
i/7);
739 for (
i=0;
i <
data->n_coefs;
i++) {
741 prod = x_powers[7 * gsl_matrix_long_get(
data->basisFunctionOrders,
i, 0)];
743 for (j=1; j<7; j++) {
744 prod *= x_powers[7 * gsl_matrix_long_get(
data->basisFunctionOrders,
i, j) + j];
746 res += gsl_vector_get(
data->coefs,
i) * prod;
763 for (
int i=0;
i <
data->vec_dim;
i++) {
820 for (
i=0;
i<4;
i++) {
826 for (
i=5;
i<8;
i++) {
832 for (
i=8;
i<11;
i++) {
838 for (
i=0;
i<4;
i++) {
842 for (
i=5;
i<8;
i++) {
843 y[
i] =
y[
i] * chiANorm / nA;
845 for (
i=8;
i<11;
i++) {
846 y[
i] =
y[
i] * chiBNorm / nB;
862 int n = quat[0]->size;
863 REAL8 *chiAx = chiA[0]->data;
864 REAL8 *chiAy = chiA[1]->data;
865 REAL8 *chiAz = chiA[2]->data;
866 REAL8 *chiBx = chiB[0]->data;
867 REAL8 *chiBy = chiB[1]->data;
868 REAL8 *chiBz = chiB[2]->data;
869 REAL8 *q0 = quat[0]->data;
870 REAL8 *qx = quat[1]->data;
871 REAL8 *qy = quat[2]->data;
872 REAL8 *qz = quat[3]->data;
875 for (
i=0;
i<n;
i++) {
876 nA = sqrt(chiAx[
i]*chiAx[
i] + chiAy[
i]*chiAy[
i] + chiAz[
i]*chiAz[
i]);
877 chiAx[
i] *= normA / nA;
878 chiAy[
i] *= normA / nA;
879 chiAz[
i] *= normA / nA;
884 for (
i=0;
i<n;
i++) {
885 nB = sqrt(chiBx[
i]*chiBx[
i] + chiBy[
i]*chiBy[
i] + chiBz[
i]*chiBz[
i]);
886 chiBx[
i] *= normB / nB;
887 chiBy[
i] *= normB / nB;
888 chiBz[
i] *= normB / nB;
892 for (
i=0;
i<n;
i++) {
893 nQ = sqrt(q0[
i]*q0[
i] + qx[
i]*qx[
i] + qy[
i]*qy[
i] + qz[
i]*qz[
i]);
911 int n = phi_vec->size;
913 REAL8 *phi = phi_vec->data;
915 REAL8 *chix = chiA[0]->data;
916 REAL8 *chiy = chiA[1]->data;
917 for (
i=0;
i<n;
i++) {
921 chix[
i] = tmp*cp + chiy[
i]*sp;
922 chiy[
i] = -1*tmp*sp + chiy[
i]*cp;
925 chix = chiB[0]->data;
926 chiy = chiB[1]->data;
927 for (
i=0;
i<n;
i++) {
931 chix[
i] = tmp*cp + chiy[
i]*sp;
932 chiy[
i] = -1*tmp*sp + chiy[
i]*cp;
954 x[1] =
y[5]*cp +
y[6]*sp;
955 x[2] = -1*
y[5]*sp +
y[6]*cp;
959 x[4] =
y[8]*cp +
y[9]*sp;
960 x[5] = -1*
y[8]*sp +
y[9]*cp;
973 REAL8 *Omega_coorb_xy,
978 REAL8 omega_quat_x, omega_quat_y;
986 omega_quat_x = Omega_coorb_xy[0]*cp - Omega_coorb_xy[1]*sp;
987 omega_quat_y = Omega_coorb_xy[0]*sp + Omega_coorb_xy[1]*cp;
988 dydt[0] = (-0.5)*
y[1]*omega_quat_x - 0.5*
y[2]*omega_quat_y;
989 dydt[1] = (-0.5)*
y[3]*omega_quat_y + 0.5*
y[0]*omega_quat_x;
990 dydt[2] = 0.5*
y[3]*omega_quat_x + 0.5*
y[0]*omega_quat_y;
991 dydt[3] = 0.5*
y[1]*omega_quat_y - 0.5*
y[2]*omega_quat_x;
997 dydt[5] = chiA_dot[0]*cp - chiA_dot[1]*sp;
998 dydt[6] = chiA_dot[0]*sp + chiA_dot[1]*cp;
999 dydt[7] = chiA_dot[2];
1000 dydt[8] = chiB_dot[0]*cp - chiB_dot[1]*sp;
1001 dydt[9] = chiB_dot[0]*sp + chiB_dot[1]*cp;
1002 dydt[10] = chiB_dot[2];
1015 gsl_interp_accel *acc = gsl_interp_accel_alloc();
1016 gsl_spline *interpolant = gsl_spline_alloc(gsl_interp_polynomial, 4);
1017 gsl_spline_init(interpolant,
x,
y, 4);
1018 REAL8 res = gsl_spline_eval(interpolant, xout, acc);
1019 gsl_spline_free(interpolant);
1020 gsl_interp_accel_free(acc);
1035 gsl_interp_accel *acc = gsl_interp_accel_alloc();
1036 gsl_spline *spline = gsl_spline_alloc(gsl_interp_cspline,
x->size);
1037 gsl_spline_init(spline,
x->data,
y->data,
x->size);
1039 gsl_vector *res = gsl_vector_alloc(xout->size);
1041 for (
size_t i=0;
i<xout->size;
i++) {
1042 tmp = gsl_spline_eval(spline, gsl_vector_get(xout,
i), acc);
1043 gsl_vector_set(res,
i, tmp);
1045 gsl_spline_free(spline);
1046 gsl_interp_accel_free(acc);
1075 REAL8 init_orbphase,
1079 REAL8 START_TIME = 100;
1086 if (fabs(omega_ref) < 1.e-10) {
1087 XLAL_PRINT_WARNING(
"WARNING: Treating omega_ref = 0 as a flag to use t_ref = t_0 = %.2f", START_TIME);
1093 "Reference frequency omega_ref=%0.4f > 0.2, too large!\n", omega_ref);
1097 for (
i=0;
i<4;
i++) y0[
i] = init_quat[
i];
1098 y0[4] = init_orbphase;
1099 for (
i=0;
i<3;
i++) {
1105 if (omega_ref < omega_min) {
1107 "Got omega_ref or omega_low=%0.4f smaller than the minimum omega=%0.4f for this configuration!", omega_ref, omega_min);
1113 gsl_vector *t_ds = __sur_data->
t_ds;
1114 while ((omega_max <= omega_ref) && (imax < t_ds->size)) {
1116 omega_min = omega_max;
1120 if (omega_max <= omega_ref) {
1125 REAL8 t_min = gsl_vector_get(t_ds, imax-1);
1126 REAL8 t_max = gsl_vector_get(t_ds, imax);
1127 REAL8 t_ref = (t_min * (omega_max - omega_ref) + t_max * (omega_ref - omega_min)) / (omega_max - omega_min);
1154 REAL8 omega, Omega_coorb_xy[2], chiA_dot[3], chiB_dot[3];
1177 gsl_vector *t_ds = __sur_data->
t_ds;
1179 int imax = t_ds->size - 1;
1180 REAL8 t1 = gsl_vector_get(t_ds, i1);
1181 REAL8 tmax = gsl_vector_get(t_ds, imax);
1182 if (t < t1 || t > tmax) {
1186 REAL8 t2 = gsl_vector_get(t_ds, i1+1);
1191 t2 = gsl_vector_get(t_ds, i1+1);
1197 if (i0 > imax-3) i0 = imax-3;
1198 REAL8 times[4], derivs[4], dydt0[11], dydt1[11], dydt2[11], dydt3[11];
1200 for (j=0; j<4; j++) times[j] = gsl_vector_get(t_ds, i0+j);
1206 for (j=0; j<11; j++) {
1207 derivs[0] = dydt0[j];
1208 derivs[1] = dydt1[j];
1209 derivs[2] = dydt2[j];
1210 derivs[3] = dydt3[j];
1222 REAL8 *dynamics_data,
1227 REAL8 init_orbphase,
1233 int imin, imax, i0, j;
1234 REAL8 tmin, tmax, t0,
dt, y_ref[11], dydt_ref[11], *node_data;
1238 t_ds = __sur_data->
t_ds;
1240 imax = t_ds->size - 1;
1241 tmin = gsl_vector_get(t_ds, imin);
1242 tmax = gsl_vector_get(t_ds, imax);
1243 while (imax - imin > 1) {
1244 i0 = (imax + imin)/2;
1245 t0 = gsl_vector_get(t_ds, i0);
1257 if (fabs(t_ref - tmin) < fabs(tmax - t_ref)) {
1266 for (j=0; j<4; j++) y_ref[j] = init_quat[j];
1267 y_ref[4] = init_orbphase;
1268 for (j=0; j<3; j++) {
1269 y_ref[5+j] = chiA0[j];
1270 y_ref[8+j] = chiB0[j];
1277 for (j=0; j<11; j++) y_ref[j] +=
dt * dydt_ref[j];
1281 node_data = dynamics_data + i0*11;
1282 for (j=0; j<11; j++) node_data[j] = y_ref[j];
1300 REAL8 *dynamics_data,
1312 gsl_vector *t_ds = __sur_data->
t_ds;
1324 t1 = gsl_vector_get(t_ds, 0);
1325 for (
i=0;
i<3;
i++) {
1326 t2 = gsl_vector_get(t_ds,
i+1);
1327 time_steps[
i] = t2 - t1;
1332 for (
i=0;
i<3;
i++ ) {
1335 node_data = dynamics_data + 11*
i;
1339 for (j=0; j<11; j++) {
1340 y_tmp[j] = node_data[j] + 0.5*time_steps[
i]*dydt[
i][j];
1345 for (j=0; j<11; j++) {
1346 y_tmp[j] = node_data[j] + 0.5*time_steps[
i]*
k2[j];
1351 for (j=0; j<11; j++) {
1352 y_tmp[j] = node_data[j] + time_steps[
i]*
k3[j];
1357 for (j=0; j<11; j++) {
1358 y_tmp[j] = node_data[j] + (time_steps[
i]/6.0)*(dydt[
i][j] + 2*
k2[j] + 2*
k3[j] +
k4[j]);
1361 node_data = node_data + 11;
1362 for (j=0; j<11; j++) {
1363 node_data[j] = y_tmp[j];
1368 node_data = dynamics_data + 33;
1379 REAL8 *dynamics_data,
1393 gsl_vector *t_ds = __sur_data->
t_ds;
1411 t1 = gsl_vector_get(t_ds, i_start);
1412 for (
i=0;
i<3;
i++) {
1413 t2 = gsl_vector_get(t_ds, i_start+
i+1);
1414 time_steps[
i] = t2 - t1;
1419 for (
i=0;
i<3;
i++ ) {
1422 node_data = dynamics_data + 11*(i0-
i);
1426 t1 = 0.5*(gsl_vector_get(t_ds, i0-
i) + gsl_vector_get(t_ds, i0-
i-1));
1427 for (j=0; j<11; j++) {
1428 y_tmp[j] = node_data[j] - 0.5*time_steps[2-
i]*dydt[3-
i][j];
1433 for (j=0; j<11; j++) {
1434 y_tmp[j] = node_data[j] - 0.5*time_steps[2-
i]*
k2[j];
1439 for (j=0; j<11; j++) {
1440 y_tmp[j] = node_data[j] - time_steps[2-
i]*
k3[j];
1445 for (j=0; j<11; j++) {
1446 y_tmp[j] = node_data[j] - (time_steps[2-
i]/6.0)*(dydt[3-
i][j] + 2*
k2[j] + 2*
k3[j] +
k4[j]);
1449 node_data = node_data - 11;
1450 for (j=0; j<11; j++) {
1451 node_data[j] = y_tmp[j];
1455 node_data = dynamics_data + (i0 - 3)*11;
1461 t1 = gsl_vector_get(t_ds, i0);
1462 for (
i=0;
i<3;
i++) {
1463 t2 = gsl_vector_get(t_ds, i0+
i+1);
1464 time_steps[
i] = t2 - t1;
1469 for (
i=0;
i<3;
i++ ) {
1472 node_data = dynamics_data + 11*(
i+i0);
1476 t1 = 0.5*(gsl_vector_get(t_ds,
i+i0) + gsl_vector_get(t_ds,
i+i0+1));
1477 for (j=0; j<11; j++) {
1478 y_tmp[j] = node_data[j] + 0.5*time_steps[
i]*dydt[
i][j];
1483 for (j=0; j<11; j++) {
1484 y_tmp[j] = node_data[j] + 0.5*time_steps[
i]*
k2[j];
1489 for (j=0; j<11; j++) {
1490 y_tmp[j] = node_data[j] + time_steps[
i]*
k3[j];
1495 for (j=0; j<11; j++) {
1496 y_tmp[j] = node_data[j] + (time_steps[
i]/6.0)*(dydt[
i][j] + 2*
k2[j] + 2*
k3[j] +
k4[j]);
1499 node_data = node_data + 11;
1500 for (j=0; j<11; j++) {
1501 node_data[j] = y_tmp[j];
1505 node_data = dynamics_data + (i0 + 3)*11;
1521 REAL8 *dynamics_data,
1534 REAL8 dt1, dt2, dt3, dt4;
1540 gsl_vector *t_ds = __sur_data->
t_ds;
1543 dt1 = time_steps[0];
1544 dt2 = time_steps[1];
1545 dt3 = time_steps[2];
1546 for (j=0; j<11; j++) {
1554 node_data = dynamics_data + 11*(i_start + 3);
1555 for (
i=i_start+4;
i< (int)t_ds->size;
i++) {
1558 dt4 = gsl_vector_get(t_ds,
i) - gsl_vector_get(t_ds,
i-1);
1562 for (j=0; j<11; j++) ynext[j] += node_data[j];
1567 for (j=0; j<11; j++) node_data[j] = ynext[j];
1570 if (
i < (
int) t_ds->size - 1) {
1574 for (j=0; j<11; j++) {
1584 dt1 = -1 * time_steps[2];
1585 dt2 = -1 * time_steps[1];
1586 dt3 = -1 * time_steps[0];
1587 for (j=0; j<11; j++) {
1595 node_data = dynamics_data + 11*(i_start);
1596 for (
i=i_start-1;
i>=0;
i--) {
1599 dt4 = gsl_vector_get(t_ds,
i) - gsl_vector_get(t_ds,
i+1);
1603 for (j=0; j<11; j++) ynext[j] += node_data[j];
1608 for (j=0; j<11; j++) node_data[j] = ynext[j];
1615 for (j=0; j<11; j++) {
1639 gsl_vector *nodes = gsl_vector_alloc(
data->n_nodes);
1641 int i, j, node_index;
1645 for (
i=0;
i<
data->n_nodes;
i++) {
1646 node_index = gsl_vector_long_get(
data->empirical_node_indices,
i);
1647 for (j=0; j<3; j++) {
1648 x[1+j] = gsl_vector_get(chiA[j], node_index);
1649 x[4+j] = gsl_vector_get(chiB[j], node_index);
1655 gsl_blas_dgemv(CblasTrans, 1.0,
data->empirical_interpolant_basis, nodes, 0.0, result);
1657 gsl_vector_free(nodes);
1676 REAL8 *dynamics_data,
1681 REAL8 init_orbphase,
1684 UINT4 PrecessingNRSurVersion
1688 UINT4 unlim_extrap = 0;
1689 if (LALparams != NULL &&
1696 REAL8 normA = sqrt(chiA0[0]*chiA0[0] + chiA0[1]*chiA0[1] + chiA0[2]*chiA0[2]);
1697 REAL8 normB = sqrt(chiB0[0]*chiB0[0] + chiB0[1]*chiB0[1] + chiB0[2]*chiB0[2]);
1702 REAL8 Q_MAX_WARN = 1;
1703 REAL8 CHI_MAX_WARN = 0;
1705 if (PrecessingNRSurVersion == 0) {
1711 }
else if (PrecessingNRSurVersion == 1) {
1719 "Only 0 or 1 are currently allowed for PrecessingNRSurVersion\n");
1724 "Invalid mass ratio q = %0.4f < 1\n",
q);
1726 if ((
q >
Q_MAX) && (unlim_extrap == 0)) {
1728 "Too much extrapolation. Mass ratio q = %0.4f > %0.4f, the "
1729 "maximum allowed value.\n",
q,
Q_MAX);
1731 if (
q > Q_MAX_WARN) {
1733 "Extrapolating to mass ratio q = %0.4f > %0.4f, the maximum "
1734 "mass ratio used to train the surrogate.\n",
q, Q_MAX_WARN);
1736 if ((normA > CHI_MAX) && (unlim_extrap == 0)) {
1738 "Too much extrapolation. Spin magnitude |chiA| = %0.4f > %.04f "
1739 "the maximum allowed .\n", normA, CHI_MAX);
1741 if ((normB > CHI_MAX) && (unlim_extrap == 0)) {
1743 "Too much extrapolation. Spin magnitude |chiB| = %0.4f > %.04f "
1744 "the maximum allowed value.\n", normB, CHI_MAX);
1746 if (normA > CHI_MAX_WARN) {
1748 "Extrapolating to spin magnitude |chiA| = %0.4f > %0.4f, the "
1749 "maximum spin magnitude used to train the surrogate.\n",
1750 normA, CHI_MAX_WARN);
1752 if (normB > CHI_MAX_WARN) {
1754 "Extrapolating to spin magnitude |chiB| = %0.4f > %0.4f, the "
1755 "maximum spin magnitude used to train the surrogate.\n",
1756 normB, CHI_MAX_WARN);
1760 init_quat, init_orbphase, __sur_data);
1773 REAL8 time_steps[3];
1774 REAL8 dydt0[11], dydt1[11], dydt2[11], dydt3[11];
1780 i_start =
PrecessingNRSur_initialize_RK4(dynamics_data, time_steps, dydt0, dydt1, dydt2, dydt3, normA, normB,
q, i0, __sur_data);
1785 PrecessingNRSur_integrate_AB4(dynamics_data, time_steps, dydt0, dydt1, dydt2, dydt3, normA, normB,
q, i_start, __sur_data);
1803 #if LAL_HDF5_ENABLED
1806 #ifdef LAL_PTHREAD_LOCK
1807 (void) pthread_once(&NRSur7dq2_is_initialized,
1808 NRSur7dq2_Init_LALDATA);
1810 NRSur7dq2_Init_LALDATA();
1818 #ifdef LAL_PTHREAD_LOCK
1819 (void) pthread_once(&NRSur7dq4_is_initialized,
1820 NRSur7dq4_Init_LALDATA);
1822 NRSur7dq4_Init_LALDATA();
1831 " and NRSur7dq4 are allowed.\n");
1854 REAL8 init_orbphase,
1856 LALValue* ModeArray,
1863 if (!__sur_data->
setup) {
1870 for (
m=-ell;
m<=ell;
m++) {
1878 gsl_vector *t_ds = __sur_data->
t_ds;
1879 gsl_vector *t_coorb = __sur_data->
t_coorb;
1880 int n_ds = t_ds->size;
1881 int n_coorb = t_coorb->size;
1887 omega_ref, init_orbphase, init_quat, LALparams,
1896 gsl_vector *dynamics[11];
1897 for (j=0; j<11; j++) {
1898 dynamics[j] = gsl_vector_alloc(n_ds);
1900 for (
i=0;
i<n_ds;
i++) {
1901 for (j=0; j<11; j++) {
1902 gsl_vector_set(dynamics[j],
i, dynamics_data[11*
i + j]);
1912 gsl_vector *quat_coorb[4], *chiA_coorb[3], *chiB_coorb[3];
1925 for (j=0; j<11; j++) {
1926 gsl_vector_free(dynamics[j]);
1930 REAL8 normA = sqrt(chiA0[0]*chiA0[0] + chiA0[1]*chiA0[1] + chiA0[2]*chiA0[2]);
1931 REAL8 normB = sqrt(chiB0[0]*chiB0[0] + chiB0[1]*chiB0[1] + chiB0[2]*chiB0[2]);
1940 gsl_vector *data_piece_eval = gsl_vector_alloc(n_coorb);
1946 i0 = ell*(ell+1) - 4;
1962 for (
m=1;
m<=ell;
m++) {
2003 for (
i=0;
i<3;
i++) {
2004 gsl_vector_free(chiA_coorb[
i]);
2005 gsl_vector_free(chiB_coorb[
i]);
2006 gsl_vector_free(quat_coorb[
i]);
2008 gsl_vector_free(quat_coorb[3]);
2009 gsl_vector_free(phi_coorb);
2010 gsl_vector_free(data_piece_eval);
2039 for (
i=1;
i<4;
i++) y0[
i] = 0.0;
2049 REAL8 f_start_Hz = omega_dimless_start / (
LAL_PI * Mtot_sec);
2179 if ( ModeArray == NULL ) {
2189 &s1x, &s1y, &s1z, &s2x, &s2y, &s2z);
2194 REAL8 Mtot = massA+massB;
2197 REAL8 chiA0[3], chiB0[3];
2205 REAL8 omegaMin_dimless;
2206 REAL8 omegaRef_dimless;
2208 fMin, fRef, Mtot_sec);
2225 REAL8 init_orbphase = 0;
2230 q, chiA0, chiB0, omegaRef_dimless, init_orbphase, init_quat,
2233 if (!h_inertial_modes) {
2239 size_t length = h_inertial_modes->
n_times;
2240 gsl_vector *hplus_model_times = gsl_vector_calloc(length);
2241 gsl_vector *hcross_model_times = gsl_vector_calloc(length);
2248 bool skip_ell_modes;
2250 REAL8 prefactor = 1;
2255 skip_ell_modes =
true;
2256 for (
m=-ell;
m<=ell;
m++) {
2258 skip_ell_modes =
false;
2261 if (skip_ell_modes) {
2265 for (
m=-ell;
m<=ell;
m++) {
2277 0.5 *
LAL_PI - phiRef, -2, ell,
m);
2278 c_re = creal(swsh_coef);
2279 c_im = cimag(swsh_coef);
2287 if ((
m%2 != 0) && (labels_switched)) {
2292 for (j=0; j < (int)length; j++) {
2295 hplus_model_times->data[j] += prefactor
2296 * (c_re * hmre - c_im * hmim);
2297 hcross_model_times->data[j] -= prefactor
2298 * (c_im * hmre + c_re * hmim);
2306 gsl_vector_scale(hplus_model_times, a0);
2307 gsl_vector_scale(hcross_model_times, a0);
2310 gsl_vector *model_times = __sur_data->
t_coorb;
2312 REAL8 t0 = gsl_vector_get(model_times, 0);
2314 if (fMin >= start_freq) {
2316 init_quat, init_orbphase, __sur_data);
2317 }
else if (fMin > 0) {
2320 gsl_vector_free(hplus_model_times);
2321 gsl_vector_free(hcross_model_times);
2325 REAL8 tf = gsl_vector_get(model_times, length-1);
2326 int nt = (int) ceil((tf - t0) / deltaT_dimless);
2327 gsl_vector *output_times = gsl_vector_alloc(nt);
2328 for (j=0; j<nt; j++) {
2329 gsl_vector_set(output_times, j, t0 + deltaT_dimless*j);
2338 gsl_interp_accel *acc = gsl_interp_accel_alloc();
2339 gsl_spline *spl_hplus = gsl_spline_alloc(gsl_interp_cspline, length);
2340 gsl_spline *spl_hcross = gsl_spline_alloc(gsl_interp_cspline, length);
2341 gsl_spline_init(spl_hplus, model_times->data, hplus_model_times->data, length);
2342 gsl_spline_init(spl_hcross, model_times->data, hcross_model_times->data, length);
2343 for (j=0; j<nt; j++) {
2344 t = gsl_vector_get(output_times, j);
2345 (*hplus)->data->data[j] = gsl_spline_eval(spl_hplus, t, acc);
2346 (*hcross)->data->data[j] = gsl_spline_eval(spl_hcross, t, acc);
2350 gsl_vector_free(hplus_model_times);
2351 gsl_vector_free(hcross_model_times);
2352 gsl_vector_free(output_times);
2353 gsl_interp_accel_free(acc);
2354 gsl_spline_free(spl_hplus);
2355 gsl_spline_free(spl_hcross);
2445 if ( ModeArray == NULL ) {
2455 &S1x, &S1y, &S1z, &S2x, &S2y, &S2z);
2460 REAL8 Mtot = massA+massB;
2463 REAL8 chiA0[3], chiB0[3];
2471 REAL8 omegaMin_dimless;
2472 REAL8 omegaRef_dimless;
2474 fMin, fRef, Mtot_sec);
2491 REAL8 init_orbphase = 0;
2496 chiA0, chiB0, omegaRef_dimless, init_orbphase, init_quat,
2508 gsl_vector *model_times = __sur_data->
t_coorb;
2510 REAL8 t0 = gsl_vector_get(model_times, 0);
2512 if (fMin >= start_freq) {
2514 init_quat, init_orbphase, __sur_data);
2515 }
else if (fMin > 0) {
2521 size_t length = model_times->size;
2522 REAL8 tf = gsl_vector_get(model_times, length-1);
2523 int nt = (int) ceil((tf - t0) / deltaT_dimless);
2524 gsl_vector *output_times = gsl_vector_alloc(nt);
2526 for (j=0; j<nt; j++) {
2527 gsl_vector_set(output_times, j, t0 + deltaT_dimless*j);
2534 gsl_interp_accel *acc = gsl_interp_accel_alloc();
2539 bool skip_ell_modes;
2541 REAL8 prefactor = 1;
2545 skip_ell_modes =
true;
2546 for (
m=-ell;
m<=ell;
m++) {
2549 if (skip_ell_modes) {
2553 for (
m=-ell;
m<=ell;
m++) {
2561 if ((
m%2 != 0) && (labels_switched)) {
2569 snprintf(mode_name,
sizeof(mode_name),
"(%d, %d) mode", ell,
m);
2572 gsl_spline *spl_re = gsl_spline_alloc(gsl_interp_cspline, length);
2573 gsl_spline *spl_im = gsl_spline_alloc(gsl_interp_cspline, length);
2574 gsl_spline_init(spl_re, model_times->data,
2576 gsl_spline_init(spl_im, model_times->data,
2578 for (j=0; j<nt; j++) {
2579 t = gsl_vector_get(output_times, j);
2580 tmp_mode->
data->
data[j] = gsl_spline_eval(spl_re, t, acc);
2581 tmp_mode->
data->
data[j] += I * gsl_spline_eval(spl_im, t, acc);
2583 gsl_spline_free(spl_re);
2584 gsl_spline_free(spl_im);
2593 gsl_vector_free(output_times);
2594 gsl_interp_accel_free(acc);
2697 gsl_vector **t_dynamics,
2702 gsl_vector **orbphase,
2716 REAL8 omegaRef_dimless,
2721 REAL8 init_orbphase,
2728 if (!__sur_data->
setup) {
2736 REAL8 chiA0[3], chiB0[3];
2737 chiA0[0] = chiA0x * cos(init_orbphase) - chiA0y * sin(init_orbphase);
2738 chiA0[1] = chiA0y * cos(init_orbphase) + chiA0x * sin(init_orbphase);
2740 chiB0[0] = chiB0x * cos(init_orbphase) - chiB0y * sin(init_orbphase);
2741 chiB0[1] = chiB0y * cos(init_orbphase) + chiB0x * sin(init_orbphase);
2746 init_quat[0] = init_quat0;
2747 init_quat[1] = init_quat1;
2748 init_quat[2] = init_quat2;
2749 init_quat[3] = init_quat3;
2753 int n_ds = (__sur_data->
t_ds)->size;
2756 chiA0, chiB0, omegaRef_dimless, init_orbphase, init_quat,
2765 gsl_vector *dynamics[11];
2766 for (j=0; j<11; j++) {
2767 dynamics[j] = gsl_vector_alloc(n_ds);
2769 for (
i=0;
i<n_ds;
i++) {
2770 for (j=0; j<11; j++) {
2771 gsl_vector_set(dynamics[j],
i, dynamics_data[11*
i + j]);
2778 *t_dynamics = gsl_vector_alloc(n_ds);
2779 gsl_vector_memcpy(*t_dynamics, __sur_data->
t_ds);
2781 *quat0 = dynamics[0];
2782 *quat1 = dynamics[1];
2783 *quat2 = dynamics[2];
2784 *quat3 = dynamics[3];
2785 *orbphase = dynamics[4];
2786 *chiAx = dynamics[5];
2787 *chiAy = dynamics[6];
2788 *chiAz = dynamics[7];
2789 *chiBx = dynamics[8];
2790 *chiBy = dynamics[9];
2791 *chiBz = dynamics[10];
struct tagLALH5File LALH5File
struct tagLALH5Dataset LALH5Dataset
int XLALDictContains(const LALDict *dict, const char *key)
UINT4 XLALDictLookupUINT4Value(const LALDict *dict, const char *key)
Auxiliary functions related to HDF5 waveform data files.
static UNUSED const double Q_MAX
static PrecessingNRSurData __lalsim_NRSur7dq2_data
Global surrogate data.
static PrecessingNRSurData __lalsim_NRSur7dq4_data
static const double NRSUR7DQ4_Q_MAX
static const double NRSUR7DQ4_Q_FIT_OFFSET
static const char NRSUR7DQ4_DATAFILE[]
static const double NRSUR7DQ4_START_TIME
static const double NRSUR7DQ4_Q_FIT_SLOPE
static const double NRSUR7DQ2_Q_FIT_SLOPE
static const double NRSUR7DQ2_Q_MAX
static const double NRSUR7DQ4_Q_MAX_WARN
static const double NRSUR7DQ2_CHI_MAX_WARN
static const int NRSUR_LMAX
static const double NRSUR7DQ2_CHI_MAX
static const double NRSUR7DQ2_Q_MAX_WARN
static const double NRSUR7DQ4_CHI_MAX_WARN
static const double NRSUR7DQ2_Q_FIT_OFFSET
static const double NRSUR7DQ4_CHI_MAX
static const double NRSUR7DQ2_START_TIME
static const char NRSUR7DQ2_DATAFILE[]
Auxiliary functions for SEOBNRv1/v2 reduced order modeling codes in LALSimIMRSEOBNRv2ROMDoubleSpin....
static void NRSur_ab4_dy(REAL8 *dy, REAL8 *k1, REAL8 *k2, REAL8 *k3, REAL8 *k4, REAL8 t12, REAL8 t23, REAL8 t34, REAL8 t45, int dim)
static void MultiModalWaveform_Destroy(MultiModalWaveform *wave)
Destroy a MultiModalWaveform structure; free all associated memory.
static void TransformModesCoorbitalToInertial(MultiModalWaveform *h, MultiModalWaveform *h_coorb, gsl_vector **quat, gsl_vector *orbphase)
Transforms modes from the coorbital frame to the inertial frame.
static void MultiModalWaveform_Init(MultiModalWaveform **wave, int LMax, int n_times)
Initialize a MultiModalWaveforme.
static UNUSED int get_dimless_omega(REAL8 *omegaMin_dimless, REAL8 *omegaRef_dimless, const REAL8 fMin, const REAL8 fRef, const REAL8 Mtot_sec)
Wrapper to get dimensionless omegaMin/omegaRef from fMin/fRef.
void XLALDestroyValue(LALValue *value)
static REAL8 sum(REAL8 *arr1, REAL8 *arr2, int k)
#define XLAL_FILE_RESOLVE_PATH(fname)
LALH5File * XLALH5GroupOpen(LALH5File UNUSED *file, const char UNUSED *name)
LALH5File * XLALH5FileOpen(const char UNUSED *path, const char UNUSED *mode)
LALH5Dataset * XLALH5DatasetRead(LALH5File UNUSED *file, const char UNUSED *name)
UINT4Vector * XLALH5DatasetQueryDims(LALH5Dataset UNUSED *dset)
void * XLALMalloc(size_t n)
void * XLALCalloc(size_t m, size_t n)
#define LAL_SIM_L_MAX_MODE_ARRAY
Maximum L spherical harmonic mode that is supported in Mode Array.
Approximant
Enum that specifies the PN approximant to be used in computing the waveform.
@ NRSur7dq4
q=4 extension of NRSur7dq2, arxiv: 1905.09300
@ NRSur7dq2
Time domain, fully precessing NR surrogate model with up to ell=4 modes, arxiv: 1705....
static REAL8 PrecessingNRSur_get_omega(size_t node_index, REAL8 q, REAL8 *y0, PrecessingNRSurData *__sur_data)
Computes the orbital angular frequency at a dynamics node.
static UNUSED bool NRSur7dq2_IsSetup(void)
Helper function which returns whether or not the global NRSur7dq2 surrogate data has been initialized...
static void PrecessingNRSur_normalize_y(REAL8 chiANorm, REAL8 chiBNorm, REAL8 *y)
static int PrecessingNRSur_initialize_RK4(REAL8 *dynamics_data, REAL8 *time_steps, REAL8 *dydt0, REAL8 *dydt1, REAL8 *dydt2, REAL8 *dydt3, REAL8 normA, REAL8 normB, REAL8 q, int i0, PrecessingNRSurData *__sur_data)
Initializes the AB4 ODE system from a single arbitrary dynamics node by taking 3 RK4 steps.
static void PrecessingNRSur_rotate_spins(gsl_vector **chiA, gsl_vector **chiB, gsl_vector *phi_vec)
Transforms chiA and chiB from the coprecessing frame to the coorbital frame using the orbital phase.
static void PrecessingNRSur_get_time_deriv_from_index(REAL8 *dydt, int i0, REAL8 q, REAL8 *y, PrecessingNRSurData *__sur_data)
Compute dydt at a given dynamics node, where y is the numerical solution to the dynamics ODE.
int XLALSimInspiralPrecessingNRSurPolarizations(REAL8TimeSeries **hplus, REAL8TimeSeries **hcross, REAL8 phiRef, REAL8 inclination, REAL8 deltaT, REAL8 m1, REAL8 m2, REAL8 distance, REAL8 fMin, REAL8 fRef, REAL8 s1x, REAL8 s1y, REAL8 s1z, REAL8 s2x, REAL8 s2y, REAL8 s2z, LALDict *LALparams, Approximant approximant)
This function evaluates the NRSur7dq2 or NRSur7dq4 surrogate model and sums over all ell <= 4 modes t...
static void PrecessingNRSur_get_time_deriv(REAL8 *dydt, REAL8 t, REAL8 q, REAL8 *y, PrecessingNRSurData *__sur_data)
Compute dydt at any time by evaluating dydt at 4 nearby dynamics nodes and using cubic spline interpo...
static void PrecessingNRSur_assemble_dydt(REAL8 *dydt, REAL8 *y, REAL8 *Omega_coorb_xy, REAL8 omega, REAL8 *chiA_dot, REAL8 *chiB_dot)
SphHarmTimeSeries * XLALSimInspiralPrecessingNRSurModes(REAL8 deltaT, REAL8 m1, REAL8 m2, REAL8 S1x, REAL8 S1y, REAL8 S1z, REAL8 S2x, REAL8 S2y, REAL8 S2z, REAL8 fMin, REAL8 fRef, REAL8 distance, LALDict *LALparams, Approximant approximant)
This function evaluates the NRSur7dq2 or NRSur7dq4 surrogate model and returns the inertial frame mod...
static void PrecessingNRSur_integrate_AB4(REAL8 *dynamics_data, REAL8 *time_steps, REAL8 *dydt0, REAL8 *dydt1, REAL8 *dydt2, REAL8 *dydt3, REAL8 normA, REAL8 normB, REAL8 q, int i_start, PrecessingNRSurData *__sur_data)
Integrates the AB4 ODE system in time forwards, and backwards if needed.
static int NRSur7dq4_effective_spins(REAL8 *chiHat, REAL8 *chi_a, const REAL8 q, const REAL8 chi1z, const REAL8 chi2z)
static PrecessingNRSurData * PrecessingNRSur_LoadData(UNUSED Approximant approximant)
Wrapper for Loading NRSur7dq2 and NRSur7dq4 data.
int XLALPrecessingNRSurDynamics(gsl_vector **t_dynamics, gsl_vector **quat0, gsl_vector **quat1, gsl_vector **quat2, gsl_vector **quat3, gsl_vector **orbphase, gsl_vector **chiAx, gsl_vector **chiAy, gsl_vector **chiAz, gsl_vector **chiBx, gsl_vector **chiBy, gsl_vector **chiBz, REAL8 q, REAL8 chiA0x, REAL8 chiA0y, REAL8 chiA0z, REAL8 chiB0x, REAL8 chiB0y, REAL8 chiB0z, REAL8 omegaRef_dimless, REAL8 init_quat0, REAL8 init_quat1, REAL8 init_quat2, REAL8 init_quat3, REAL8 init_orbphase, LALDict *LALparams, Approximant approximant)
This function evaluates the NRSur7dq2 or NRSur7dq4 surrogate model and returns the precessing frame d...
static int PrecessingNRSur_initialize_at_dynamics_node(REAL8 *dynamics_data, REAL8 t_ref, REAL8 q, REAL8 *chiA0, REAL8 *chiB0, REAL8 init_orbphase, REAL8 *init_quat, REAL8 normA, REAL8 normB, PrecessingNRSurData *__sur_data)
Initialize the dynamics ODE at a dynamics node.
static void PrecessingNRSur_normalize_results(REAL8 normA, REAL8 normB, gsl_vector **quat, gsl_vector **chiA, gsl_vector **chiB)
static int PrecessingNRSur_IntegrateDynamics(REAL8 *dynamics_data, REAL8 q, REAL8 *chiA0, REAL8 *chiB0, REAL8 omega_ref, REAL8 init_orbphase, REAL8 *init_quat, LALDict *LALparams, UINT4 PrecessingNRSurVersion)
This is the main NRSur dynamics surrogate integration routine.
static void NRSur7dq4_eval_vector_fit(REAL8 *res, VectorFitData *data, REAL8 *x)
REAL8 NRSur7dq4_eval_fit(FitData *data, REAL8 *x)
static gsl_vector * spline_array_interp(gsl_vector *xout, gsl_vector *x, gsl_vector *y)
Do cubic spline interpolation using a gsl_interp_cspline.
static PrecessingNRSurData * PrecessingNRSur_core(MultiModalWaveform **h, REAL8 q, REAL8 *chiA0, REAL8 *chiB0, REAL8 omega_ref, REAL8 init_orbphase, REAL8 *init_quat, LALValue *ModeArray, LALDict *LALparams, Approximant approximant)
static void NRSur7dq2_eval_vector_fit(REAL8 *res, VectorFitData *data, REAL8 *x)
static bool PrecessingNRSur_switch_labels_if_needed(REAL8 *m1, REAL8 *m2, REAL8 *s1x, REAL8 *s1y, REAL8 *s1z, REAL8 *s2x, REAL8 *s2y, REAL8 *s2z)
If m1<m2, swaps the labels for the two BHs such that Bh1 is always heavier.
REAL8 ipow(REAL8 base, int exponent)
Helper function for integer powers.
static void PrecessingNRSur_eval_vector_fit(REAL8 *res, VectorFitData *data, REAL8 *x, PrecessingNRSurData *__sur_data)
static UNUSED bool NRSur7dq4_IsSetup(void)
Helper function which returns whether or not the global NRSur7dq4 surrogate data has been initialized...
static REAL8 PrecessingNRSur_get_t_ref(REAL8 omega_ref, REAL8 q, REAL8 *chiA0, REAL8 *chiB0, REAL8 *init_quat, REAL8 init_orbphase, PrecessingNRSurData *__sur_data)
Computes a reference time from a reference orbital angular frequency.
REAL8 PrecessingNRSur_eval_fit(FitData *data, REAL8 *x, PrecessingNRSurData *__sur_data)
static void PrecessingNRSur_initialize_RK4_with_half_nodes(REAL8 *dynamics_data, REAL8 *time_steps, REAL8 *dydt0, REAL8 *dydt1, REAL8 *dydt2, REAL8 *dydt3, REAL8 normA, REAL8 normB, REAL8 q, PrecessingNRSurData *__sur_data)
Initializes the AB4 ODE system from the surrogate start time by taking 3 RK4 steps,...
static void PrecessingNRSur_eval_data_piece(gsl_vector *result, REAL8 q, gsl_vector **chiA, gsl_vector **chiB, WaveformDataPiece *data, PrecessingNRSurData *__sur_data)
Evaluates a single NRSur coorbital waveoform data piece.
static void PrecessingNRSur_ds_fit_x(REAL8 *x, REAL8 q, REAL8 *y)
REAL8 PrecessingNRSur_StartFrequency(REAL8 m1, REAL8 m2, REAL8 s1x, REAL8 s1y, REAL8 s1z, REAL8 s2x, REAL8 s2y, REAL8 s2z, PrecessingNRSurData *__sur_data)
Computes the starting frequency of the NRSur7dq2 or NRSur7dq4 waveform approximant when evaluated usi...
REAL8 NRSur7dq2_eval_fit(FitData *data, REAL8 *x)
static REAL8 cubic_interp(REAL8 xout, REAL8 *x, REAL8 *y)
Cubic interpolation of 4 data points This gives a much closer result to scipy.interpolate....
SphHarmTimeSeries * XLALSphHarmTimeSeriesAddMode(SphHarmTimeSeries *appended, const COMPLEX16TimeSeries *inmode, UINT4 l, INT4 m)
Prepend a node to a linked list of SphHarmTimeSeries, or create a new head.
COMPLEX16 XLALSpinWeightedSphericalHarmonic(REAL8 theta, REAL8 phi, int s, int l, int m)
void XLALDestroyCOMPLEX16TimeSeries(COMPLEX16TimeSeries *series)
COMPLEX16TimeSeries * XLALCreateCOMPLEX16TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
REAL8TimeSeries * XLALCreateREAL8TimeSeries(const CHAR *name, const LIGOTimeGPS *epoch, REAL8 f0, REAL8 deltaT, const LALUnit *sampleUnits, size_t length)
const LALUnit lalStrainUnit
#define XLAL_ERROR_VOID(...)
#define XLAL_ERROR_REAL8(...)
#define XLAL_PRINT_INFO(...)
#define XLAL_ERROR_NULL(...)
#define XLAL_PRINT_WARNING(...)
#define XLAL_CHECK_ABORT(assertion)
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
#define XLAL_IS_REAL8_FAIL_NAN(val)
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
Data for a single dynamics node.
FitData * omega_data
A fit to the orbital angular frequency.
VectorFitData * chiB_dot_data
A 3d vector fit for the coorbital components of the time derivative of chiB taken in the coprecessing...
VectorFitData * chiA_dot_data
A 3d vector fit for the coorbital components of the time derivative of chiA taken in the coprecessing...
VectorFitData * omega_copr_data
A 2d vector fit for the x and y components of Omega^{coorb}(t) in arxiv 1705.07089.
Data used in a single scalar fit.
int n_coefs
Number of coefficients in the fit.
gsl_matrix_long * basisFunctionOrders
matrix of (n_coefs x 7) basis function orders giving the polynomial order in f(q),...
gsl_vector * coefs
coefficient vector of length n_coefs
All data needed by the full surrogate model.
gsl_vector * t_coorb
Vector of the coorbital surrogate output times.
UINT4 PrecessingNRSurVersion
One for each 2 <= ell <= LMax.
WaveformFixedEllModeData ** coorbital_mode_data
A DynamicsNodeFitData for each time in t_ds_half_times.
DynamicsNodeFitData ** ds_half_node_data
A DynamicsNodeFitData for each time in t_ds.
UINT4 setup
Indicates if this has been initialized.
DynamicsNodeFitData ** ds_node_data
Structure to carry a collection of spherical harmonic modes in COMPLEX16 time series.
Data used in a single vector fit NOTE: basisFunctionOrders, coefs, componentIndices,...
int n_coefs
Number of coefficients in the fit.
gsl_matrix_long * basisFunctionOrders
matrix of (n_coefs x 7) basis function orders giving the polynomial order in f(q),...
int vec_dim
Dimension of the vector.
gsl_vector_long * componentIndices
Each fit coefficient applies to a single component of the vector; this gives the component indices.
gsl_vector * coefs
coefficient vector of length n_coefs