32 #define UNUSED __attribute__ ((unused))
40 #include <gsl/gsl_bspline.h>
41 #include <gsl/gsl_blas.h>
42 #include <gsl/gsl_spline.h>
43 #include <gsl/gsl_complex_math.h>
45 #include <lal/SeqFactories.h>
46 #include <lal/H5FileIO.h>
48 #include <lal/XLALError.h>
49 #include <lal/LALConstants.h>
50 #include <lal/LALSimIMR.h>
76 if(
data == NULL ||
data->length != 1) {
79 "Failed to load `%s' scalar dataset\n",
name);
82 *param =
data->data[0];
100 if(
data == NULL ||
data->length != 1) {
103 "Failed to load `%s' scalar dataset\n",
name);
106 *param = (int)
data->data[0];
126 const char *sub_grp_name
129 if (data_piece == NULL || *data_piece != NULL) {
141 gsl_matrix *ei_basis = NULL;
142 int ret = ReadHDF5RealMatrixDataset(sub,
"ei_basis", &ei_basis);
147 (*data_piece)->ei_basis = ei_basis;
156 (*data_piece)->n_nodes = n_nodes;
160 const size_t str_size = 20;
162 UNUSED
size_t nwritten;
163 for (
int i=0;
i<n_nodes;
i++) {
165 nwritten = snprintf(node_name, str_size,
"node_num_%d",
i);
174 node_function,
"constant_value");
181 node_function,
"y_train_mean");
188 node_function,
"data_mean");
195 node_function,
"data_std");
202 node_function,
"lin_intercept");
211 ret = ReadHDF5RealVectorDataset(node_function,
"length_scale",
218 hyperparams->
alpha = NULL;
219 ret = ReadHDF5RealVectorDataset(node_function,
"alpha",
220 &(hyperparams->
alpha));
227 ret = ReadHDF5RealVectorDataset(node_function,
"lin_coef",
237 (*data_piece)->fit_data[
i] = fit_data;
255 const gsl_matrix_long *mode_list
258 if (mode_data_pieces == NULL) {
266 const UINT4 ell = gsl_matrix_long_get(mode_list, mode_idx, 0);
267 const UINT4 m = gsl_matrix_long_get(mode_list, mode_idx, 1);
270 =
XLALMalloc(
sizeof(*mode_data_pieces[mode_idx]));
272 data_pieces->
ell = ell;
283 const size_t str_size = 20;
286 UNUSED
size_t nwritten;
287 if (ell == 2 &&
m ==2){
290 nwritten = snprintf(sub_grp_name, str_size,
"l%u_m%u/amp", ell,
m);
297 "Failed to load `%s' data piece", sub_grp_name);
301 nwritten = snprintf(sub_grp_name, str_size,
"l%u_m%u/phase", ell,
m);
308 "Failed to load `%s' data piece", sub_grp_name);
315 if (
m != 0 || ell % 2 == 0) {
317 nwritten = snprintf(sub_grp_name, str_size,
"l%u_m%u/re", ell,
m);
324 "Failed to load `%s' data piece", sub_grp_name);
331 if (
m != 0 || ell % 2 == 1) {
333 nwritten = snprintf(sub_grp_name, str_size,
"l%u_m%u/im", ell,
m);
340 "Failed to load `%s' data piece", sub_grp_name);
345 mode_data_pieces[mode_idx] = data_pieces;
408 if (NR_hybsur_data == NULL) {
415 if (NR_hybsur_data->
setup) {
417 "Model was already initialized. Ignoring.");
420 gsl_vector *domain = NULL;
421 int ret = ReadHDF5RealVectorDataset(
file,
"domain", &domain);
425 NR_hybsur_data->
domain = domain;
427 gsl_matrix *x_train = NULL;
428 ret = ReadHDF5RealMatrixDataset(
file,
"GPR_X_train", &x_train);
432 NR_hybsur_data->
x_train = x_train;
437 gsl_matrix_long *mode_list = NULL;
438 ret = ReadHDF5LongMatrixDataset(
file,
"mode_list", &mode_list);
444 UINT4 num_modes_modeled = mode_list->size1;
449 *
sizeof(*mode_data_pieces));
458 REAL8 TaylorT3_t_ref;
465 gsl_vector *TaylorT3_factor_without_eta = gsl_vector_alloc(domain->size);
466 if (TaylorT3_factor_without_eta == NULL){
470 for (
UINT4 i=0;
i<domain->size;
i++){
471 const REAL8 tVal = gsl_vector_get(domain,
i);
472 const REAL8 theta_without_eta = pow((TaylorT3_t_ref - tVal)/5., -1./8);
473 gsl_vector_set(TaylorT3_factor_without_eta,
i,
474 -2./pow(theta_without_eta, 5));
479 for (
UINT4 mode_idx = 0; mode_idx < num_modes_modeled; mode_idx++) {
481 mode_idx, mode_list);
490 NR_hybsur_data->
setup = 1;
521 const gsl_vector *x1,
522 const gsl_vector *x2,
524 gsl_vector *dummy_worker
530 (x1->size == x2->size) && (x1->size == ls.size)
531 && (x1->size == dummy_worker->size),
XLAL_EDIMS,
532 "Mismatch in size of x1, x2, dummy_worker, ls: %zu, %zu, %zu, %zu.\n",
533 x1->size, x2->size, dummy_worker->size, ls.size);
535 gsl_vector_memcpy(dummy_worker, x1);
536 gsl_vector_sub(dummy_worker, x2);
537 gsl_vector_div(dummy_worker, &ls);
538 const REAL8 r = gsl_blas_dnrm2(dummy_worker);
549 const gsl_vector *xst,
552 const gsl_matrix *x_train,
553 gsl_vector *dummy_worker
557 const UINT4 n = x_train->size1;
558 gsl_vector *Kst = gsl_vector_alloc(n);
563 const gsl_vector
x = gsl_matrix_const_row(x_train,
i).vector;
564 const REAL8 ker =
kernel(xst, &
x, hyperparams, dummy_worker);
565 gsl_vector_set(Kst,
i, ker);
570 gsl_blas_ddot(Kst, hyperparams->
alpha, &res);
571 gsl_vector_free(Kst);
583 const gsl_vector *fit_params,
585 const gsl_matrix *x_train,
586 gsl_vector *dummy_worker
591 x_train, dummy_worker);
598 gsl_vector_memcpy(dummy_worker, fit_data->
lin_coef);
599 gsl_vector_mul(dummy_worker, fit_params);
600 for (
UINT4 i=0;
i < dummy_worker->size;
i++) {
601 fit_val += gsl_vector_get(dummy_worker,
i);
614 const gsl_vector *fit_params,
617 const gsl_matrix *x_train,
618 gsl_vector *dummy_worker
621 gsl_vector *nodes = gsl_vector_alloc(data_piece->
n_nodes);
627 fit_params, x_train, dummy_worker);
628 gsl_vector_set(nodes,
i, fit_val);
632 gsl_blas_dgemv(CblasTrans, 1.0, data_piece->
ei_basis, nodes, 0.0, *result);
633 gsl_vector_free(nodes);
651 const gsl_vector *xout,
656 gsl_interp_accel *acc = gsl_interp_accel_alloc();
657 gsl_spline *spline = gsl_spline_alloc(gsl_interp_cspline,
x->size);
658 gsl_spline_init(spline,
x->data,
y->data,
x->size);
660 gsl_vector *res = gsl_vector_alloc(xout->size);
662 for (
UINT4 i=0;
i<xout->size;
i++) {
663 tmp = gsl_spline_eval(spline, gsl_vector_get(xout,
i), acc);
664 gsl_vector_set(res,
i, tmp);
666 gsl_spline_free(spline);
667 gsl_interp_accel_free(acc);
675 const gsl_vector *times,
676 const gsl_vector *phi_22,
679 const REAL8 t_next = gsl_vector_get(times, idx+1);
680 const REAL8 t = gsl_vector_get(times, idx);
681 const REAL8 phase_next = gsl_vector_get(phi_22, idx+1);
682 const REAL8 phase = gsl_vector_get(phi_22, idx);
685 const REAL8 omegaM_22 = (phase_next - phase)/(t_next - t);
697 const gsl_vector *times,
698 const gsl_vector *phi_22,
699 const REAL8 omegaM_22_val
701 REAL8 omegaM_22 = -10;
702 REAL8 omegaM_22_prev = -10;
704 while (omegaM_22 < omegaM_22_val){
706 omegaM_22_prev = omegaM_22;
712 if (gsl_vector_get(times, idx) > 0){
714 "fMin or fRef is larger than the peak frequency=%.7f,"
715 " reduce it. Note that this is in code units, radians/M.",
723 if (fabs(omegaM_22_prev - omegaM_22_val) < fabs(omegaM_22-omegaM_22_val)){
741 gsl_vector **phi_22_sparse,
744 const gsl_vector *fit_params,
746 gsl_vector *dummy_dp,
747 const gsl_matrix *x_train,
748 gsl_vector *dummy_worker,
756 if (data_pieces->
ell != 2 || data_pieces->
m != 2){
768 gsl_vector_memcpy(*phi_22_sparse, dummy_dp);
772 gsl_vector *phi_22_T3 = gsl_vector_alloc((*phi_22_sparse)->size);
774 gsl_vector_scale(phi_22_T3, 1./pow(eta, 3./8.));
778 gsl_vector_add_constant(phi_22_T3,
779 -gsl_vector_get(phi_22_T3, phaseAlignIdx));
782 gsl_vector_add(*phi_22_sparse, phi_22_T3);
784 gsl_vector_free(phi_22_T3);
795 gsl_vector **phi_22_dense,
796 gsl_vector **times_dense,
797 const REAL8 deltaTOverM,
798 const REAL8 omegaM_22_min,
799 const gsl_vector *phi_22_sparse,
800 const gsl_vector *domain
804 const REAL8 min_allowed_omegaM_22
806 if (omegaM_22_min < min_allowed_omegaM_22){
808 "fMin=%.7f is lesser than the minimum allowed value=%.7f."
809 " Note that these are in code units, radians/M.",
810 omegaM_22_min, min_allowed_omegaM_22);
816 int ret =
search_omega_22(&init_idx, domain, phi_22_sparse, omegaM_22_min);
832 gsl_vector *domain_trunc
833 = gsl_vector_alloc(phi_22_sparse->size - init_idx);
834 gsl_vector *phi_22_sparse_trunc = gsl_vector_alloc(domain_trunc->size);
835 for (
UINT4 j=0; j < domain_trunc->size; j++) {
836 gsl_vector_set(domain_trunc, j, gsl_vector_get(domain, j+init_idx));
837 gsl_vector_set(phi_22_sparse_trunc, j,
838 gsl_vector_get(phi_22_sparse, j+init_idx));
843 const REAL8 t0 = gsl_vector_get(domain_trunc, 0);
846 const REAL8 tf = gsl_vector_get(domain_trunc, domain_trunc->size-1);
850 const int num_times = (int) ceil((tf - t0)/deltaTOverM);
851 *times_dense = gsl_vector_alloc(num_times);
852 for (
int j=0; j < num_times; j++) {
853 gsl_vector_set(*times_dense, j, t0 + deltaTOverM*j);
858 phi_22_sparse_trunc);
860 gsl_vector_free(phi_22_sparse_trunc);
861 gsl_vector_free(domain_trunc);
889 gsl_vector **output_times,
891 const gsl_vector *fit_params,
893 const REAL8 omegaM_22_min,
894 const REAL8 deltaTOverM,
896 const REAL8 omegaM_22_ref,
897 gsl_vector *dummy_dp,
898 const gsl_matrix *x_train,
899 gsl_vector *dummy_worker,
903 if (omegaM_22_ref + 1
e-13 < omegaM_22_min){
908 const gsl_vector *domain = NR_hybsur_data->
domain;
909 gsl_vector *phi_22_sparse = gsl_vector_alloc(domain->size);
911 dummy_dp, x_train, dummy_worker, NR_hybsur_data);
918 gsl_vector *phi_22_dense = NULL;
919 gsl_vector *times_dense = NULL;
921 omegaM_22_min, phi_22_sparse, domain);
922 gsl_vector_free(phi_22_sparse);
936 *output_times = gsl_vector_alloc(times_dense->size - start_idx);
937 *phi_22 = gsl_vector_alloc((*output_times)->size);
938 for (
UINT4 i=0;
i < (*output_times)->size;
i++){
939 gsl_vector_set(*phi_22,
i, gsl_vector_get(phi_22_dense,
i+start_idx));
940 gsl_vector_set(*output_times,
i,
941 gsl_vector_get(times_dense,
i+start_idx));
943 gsl_vector_free(phi_22_dense);
944 gsl_vector_free(times_dense);
952 if (fabs(omegaM_22_ref - omegaM_22_min)/omegaM_22_min > 1
e-13){
953 ret =
search_omega_22(&ref_idx, *output_times, *phi_22, omegaM_22_ref);
960 gsl_vector_add_constant(*phi_22,
961 -gsl_vector_get(*phi_22,ref_idx)+2*phiRef);
984 const gsl_vector *output_times,
985 const gsl_vector *fit_params,
987 gsl_vector *dummy_dp,
988 const gsl_matrix *x_train,
989 gsl_vector *dummy_worker,
994 const gsl_vector *domain = NR_hybsur_data->
domain;
995 (*this_mode_eval_dp)->ell = ell;
996 (*this_mode_eval_dp)->m =
m;
998 if (ell == 2 &&
m ==2){
1007 (*this_mode_eval_dp)->ampl_eval
1014 if (
m != 0 || ell % 2 == 0) {
1024 (*this_mode_eval_dp)->coorb_re_eval
1031 if (
m != 0 || ell % 2 == 1) {
1042 (*this_mode_eval_dp)->coorb_im_eval
1059 const UINT4 num_modes_incl
1063 gsl_vector_free(phi_22);
1066 for (
UINT4 mode_idx = 0; mode_idx < num_modes_incl; mode_idx++){
1068 const UINT4 ell = this_mode_eval_dp->
ell;
1069 const UINT4 m = this_mode_eval_dp->
m;
1071 if (ell == 2 &&
m ==2){
1074 gsl_vector_free(this_mode_eval_dp->
ampl_eval);
1078 if (
m != 0 || ell % 2 == 0) {
1084 if (
m != 0 || ell % 2 == 1) {
1115 modefreqVec.
data = &modeFreq;
1118 UINT4 mode_highest_freqL = max_ell;
1119 UINT4 mode_highest_freqM = max_ell;
1120 UINT4 num_overtones = 1;
1123 const REAL8 spin1[3] = {0, 0, chi1z};
1124 const REAL8 spin2[3] = {0, 0, chi2z};
1129 mode_highest_freqM, num_overtones, SpinAlignedEOBapproximant);
1135 const REAL8 ringdown_freq = creal(modeFreq)/(2.*
LAL_PI);
1137 if (nyquist_freq < ringdown_freq){
1139 " frequency=%.7f Hz of the (%u,%u,0) mode. Consider reducing time"
1140 " step.", nyquist_freq, ringdown_freq, max_ell, max_ell);
1152 LALValue *ModeArray,
1157 const gsl_matrix_long *mode_list = NR_hybsur_data->
mode_list;
1161 for (
UINT4 idx = 0; idx < num_modes_modeled; idx++){
1162 ell = gsl_matrix_long_get(mode_list, idx, 0);
1163 m = gsl_matrix_long_get(mode_list, idx, 1);
1176 UINT4 *num_modes_incl,
1178 LALValue *ModeArray,
1182 INT4 modeAvailable = 0;
1188 const gsl_matrix_long *mode_list = NR_hybsur_data->
mode_list;
1190 *num_modes_incl = 0;
1193 for (
UINT4 EMM = 0; EMM <= ELL; EMM++) {
1198 for (
UINT4 idx = 0; idx < num_modes_modeled; idx++){
1200 ell = gsl_matrix_long_get(mode_list, idx, 0);
1201 m = gsl_matrix_long_get(mode_list, idx, 1);
1204 if ((ell == ELL) && (
m == EMM)) {
1206 *num_modes_incl += 1;
1207 if (ell > *max_ell) {
1213 if (modeAvailable != 1) {
1215 "Mode (%d,%d) is not available.",ELL,EMM);
1221 if (*num_modes_incl == 0) {
struct tagLALH5File LALH5File
Auxiliary functions for SEOBNRv1/v2 reduced order modeling codes in LALSimIMRSEOBNRv2ROMDoubleSpin....
static REAL8 compute_omega_22(const gsl_vector *times, const gsl_vector *phi_22, const int idx)
Computes omega_22 by forward differences.
static REAL8 kernel(const gsl_vector *x1, const gsl_vector *x2, const GPRHyperParams *hyperparams, gsl_vector *dummy_worker)
The GPR Kernel evaluated at a single pair of points.
int NRHybSur_check_mode_array(UINT4 *num_modes_incl, UINT4 *max_ell, LALValue *ModeArray, const NRHybSurData *NR_hybsur_data)
Sanity checks on ModeArray.
int ReadHDF5DoubleDataset(REAL8 *param, LALH5File *sub, const char *name)
Reads a REAL8 value from a H5 file/group.
static REAL8 gp_predict(const gsl_vector *xst, const GPRHyperParams *hyperparams, const gsl_matrix *x_train, gsl_vector *dummy_worker)
Evaluate a GPR fit.
void NRHybSur_set_default_modes(LALValue *ModeArray, const NRHybSurData *NR_hybsur_data)
Activates all modes of an NRHybSur model.
static int NRHybSur_eval_data_piece(gsl_vector **result, const gsl_vector *fit_params, const DataPiece *data_piece, const gsl_matrix *x_train, gsl_vector *dummy_worker)
Evaluate a single NRHybSur waveform data piece.
int ReadHDF5IntDataset(int *param, LALH5File *sub, const char *name)
Reads an INT8 value from a H5 file/group.
static int NRHybSur_eval_phase_22_sparse(gsl_vector **phi_22_sparse, const REAL8 eta, const gsl_vector *fit_params, gsl_vector *dummy_dp, const gsl_matrix *x_train, gsl_vector *dummy_worker, const NRHybSurData *NR_hybsur_data)
Evaluate the phase of the (2,2) mode on the sprase surrogate domain.
int NRHybSur_eval_phase_22(gsl_vector **phi_22, gsl_vector **output_times, const REAL8 eta, const gsl_vector *fit_params, const REAL8 omegaM_22_min, const REAL8 deltaTOverM, const REAL8 phiRef, const REAL8 omegaM_22_ref, gsl_vector *dummy_dp, const gsl_matrix *x_train, gsl_vector *dummy_worker, const NRHybSurData *NR_hybsur_data)
Evaluate the phase of the (2,2) mode.
static int NRHybSur_upsample_phi_22(gsl_vector **phi_22_dense, gsl_vector **times_dense, const REAL8 deltaTOverM, const REAL8 omegaM_22_min, const gsl_vector *phi_22_sparse, const gsl_vector *domain)
Upsamples sparse such that time step size is deltaTOverM, and initial frequency is roughly omegaM_22...
int NRHybSur_eval_mode_data_pieces(EvaluatedDataPieces **this_mode_eval_dp, const UINT4 ell, const UINT4 m, const ModeDataPieces *data_pieces, const gsl_vector *output_times, const gsl_vector *fit_params, gsl_vector *dummy_dp, const gsl_matrix *x_train, gsl_vector *dummy_worker, const NRHybSurData *NR_hybsur_data)
Evaluate waveform data pieces of a single mode.
static int search_omega_22(int *omega_idx, const gsl_vector *times, const gsl_vector *phi_22, const REAL8 omegaM_22_val)
Finds closest index such that omegaM_22[index] = omegaM_22_val.
int NRHybSur_sanity_check_sample_rate(REAL8 deltaT, REAL8 m1, REAL8 m2, REAL8 chi1z, REAL8 chi2z, UINT4 max_ell)
Sanity check (warning only, not error) that the sample rate is high enough to capture the ringdown fr...
REAL8 NRHybSur_eval_fit(const NRHybSurFitData *fit_data, const gsl_vector *fit_params, const gsl_matrix *x_train, gsl_vector *dummy_worker)
Evaluate a NRHybSur fit.
void NRHybSur_DestroyEvaluatedDataPieces(gsl_vector *phi_22, EvaluatedDataPieces **evaluated_mode_dps, const UINT4 num_modes_incl)
Destroy phi_22 and an EvaluatedDataPieces structure.
static gsl_vector * spline_array_interp(const gsl_vector *xout, const gsl_vector *x, const gsl_vector *y)
Do cubic spline interpolation using a gsl_interp_cspline.
int NRHybSur_Init(NRHybSurData *NR_hybsur_data, LALH5File *file)
Initialize a NRHybSurData structure from an open H5 file.
static int NRHybSur_LoadDataPiece(DataPiece **data_piece, LALH5File *file, const char *sub_grp_name)
Loads a single waveform data piece from a H5 file.
static int NRHybSur_LoadSingleModeData(ModeDataPieces **mode_data_pieces, LALH5File *file, const int mode_idx, const gsl_matrix_long *mode_list)
Loads all data pieces of a single waveform mode.
Utilities needed for aligned-spin NR-hybrid surrogate models.
REAL8Vector * XLALH5FileReadREAL8Vector(LALH5File *file, const char *name)
INT8Vector * XLALH5FileReadINT8Vector(LALH5File *file, const char *name)
void XLALH5FileClose(LALH5File UNUSED *file)
LALH5File * XLALH5GroupOpen(LALH5File UNUSED *file, const char UNUSED *name)
void * XLALMalloc(size_t n)
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.
#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.
@ SEOBNRv4
Spin nonprecessing EOBNR model v4.
void XLALDestroyREAL8Vector(REAL8Vector *vector)
void XLALDestroyINT8Vector(INT8Vector *vector)
#define XLAL_CHECK(assertion,...)
#define XLAL_PRINT_WARNING(...)
#define XLAL_CHECK_ABORT(assertion)
NRHybSur data for a single waveform data piece.
int n_nodes
Number of empirical nodes.
NRHybSurFitData ** fit_data
NRHybSurFitData at each empirical node.
gsl_matrix * ei_basis
Empirical interpolation matrix.
NRHybSur evaluated data for a single mode.
gsl_vector * coorb_re_eval
Coorbital frame real part evaluation.
gsl_vector * ampl_eval
Amplitude data piece evaluation.
gsl_vector * coorb_im_eval
Coorbital frame imag part evaluation.
Data used in a single GPR fit.
REAL8 constant_value
in kernel.
gsl_vector * alpha
Precomputed .
gsl_vector * length_scale
in kernel.
REAL8 y_train_mean
Mean value before GPR fit, usually zero.
NRHybSur data pieces of a single mode.
DataPiece * phase_res_data_piece
Phase residual data piece.
DataPiece * ampl_data_piece
Amplitude data piece.
DataPiece * coorb_im_data_piece
Coorbital frame imag part data piece.
DataPiece * coorb_re_data_piece
Coorbital frame real part data piece.
NRHybSur surrogate data for all modes, to be loaded from a h5 file.
ModeDataPieces ** mode_data_pieces
Data pieces of all modes, same order as mode_list.
gsl_vector * domain
Common time samples for the surrogate.
gsl_vector * TaylorT3_factor_without_eta
Precomputed quantity for use in evaluating the 0PN TaylorT3 phase contribution.
REAL8 params_dim
Dimensions of the model.
UINT4 setup
Indicates if NRHybSur has been initialized.
gsl_matrix * x_train
Training set parameters, needed for GPR fits.
int phaseAlignIdx
Alignment index for phase data piece.
UINT4 num_modes_modeled
Number of modeled modes.
gsl_matrix_long * mode_list
List of modeled modes, first element is always (2,2).
Data used in a single NRHybSur fit.
REAL8 data_std
Standard deviation after removing mean.
REAL8 data_mean
Mean of data after linear fit.
GPRHyperParams * hyperparams
Hyperparameters from GPR fit.
gsl_vector * lin_coef
Linear coefs from linear fit, size=D.
REAL8 lin_intercept
Constant intercept from linear fit.