/// /// Compute the determinant of a metric \f$ g_{ij} \f$. /// double XLALMetricDeterminant( const gsl_matrix *g_ij ///< [in] Parameter-space metric \f$ g_{ij} \f$ ) { // Check input XLAL_CHECK_REAL8( g_ij != NULL, XLAL_EFAULT ); const size_t n = g_ij->size1; // Allocate memory gsl_matrix *GAMAT_REAL8( LU_decomp, n, n ); gsl_permutation *GAPERM_REAL8( LU_perm, n ); // Compute LU decomposition gsl_matrix_memcpy( LU_decomp, g_ij ); int LU_sign = 0; XLAL_CHECK_REAL8( gsl_linalg_LU_decomp( LU_decomp, LU_perm, &LU_sign ) == 0, XLAL_EFAILED, "'g_ij' cannot be LU-decomposed" ); // Compute determinant const double determinant = gsl_linalg_LU_det( LU_decomp, LU_sign ); // Cleanup GFMAT( LU_decomp ); GFPERM( LU_perm ); return determinant; }
/// /// Calculate the projected metric onto the subspace orthogonal to coordinate-axis \c c, namely /// \f$ g^{\prime}_{ij} = g_{ij} - ( g_{ic} g_{jc} / g_{cc} ) \f$, where \f$c\f$ is the index of /// the projected coordinate. /// /// \note \c *p_gpr_ij will be allocated if \c NULL. \c *p_gpr_ij and \c g_ij may point to the same /// matrix. /// int XLALProjectMetric( gsl_matrix **p_gpr_ij, ///< [in,out] Pointer to projected matrix \f$g^{\prime}_{ij}\f$ const gsl_matrix *g_ij, ///< [in] Matrix to project \f$g_{ij}\f$ const UINT4 c ///< [in] Index of projected coordinate ) { // Check input XLAL_CHECK( g_ij != NULL, XLAL_EFAULT ); XLAL_CHECK( g_ij->size1 == g_ij->size2, XLAL_ESIZE ); XLAL_CHECK( p_gpr_ij != NULL, XLAL_EFAULT ); if ( *p_gpr_ij != NULL ) { XLAL_CHECK( (*p_gpr_ij)->size1 == (*p_gpr_ij)->size2, XLAL_ESIZE ); XLAL_CHECK( (*p_gpr_ij)->size1 == g_ij->size1, XLAL_ESIZE ); } else { GAMAT( *p_gpr_ij, g_ij->size1, g_ij->size2 ); } XLAL_CHECK( c < g_ij->size1, XLAL_EINVAL ); // Allocate temporary matrix gsl_matrix *GAMAT( ret_ij, g_ij->size1, g_ij->size2 ); // Compute projected matrix for ( UINT4 i=0; i < g_ij->size1; i++) { for ( UINT4 j=0; j < g_ij->size2; j++ ) { if ( i==c || j==c ) { gsl_matrix_set ( ret_ij, i, j, 0.0 ); } else { double proj = gsl_matrix_get(g_ij, i, j) - (gsl_matrix_get(g_ij, i, c) * gsl_matrix_get(g_ij, j, c) / gsl_matrix_get(g_ij, c, c)); gsl_matrix_set ( ret_ij, i, j, proj ); } } /* for j < dim2 */ } /* for i < dim1 */ gsl_matrix_memcpy( *p_gpr_ij, ret_ij ); // Cleanup GFMAT( ret_ij ); return XLAL_SUCCESS; } // XLALProjectMetric()
/// /// Diagonally-normalize a metric \f$ g_{ij} \f$. <i>Diagonally-normalize</i> means normalize /// metric by its diagonal, namely apply the transformation \f$ g_{ij} \rightarrow g^{\prime}_{ij} = /// g_{ij} / \sqrt{g_{ii} g_{jj}} \f$, resulting in a lower condition number and unit diagonal /// elements. /// /// If \c p_transform is non-NULL, return the diagonal-normalization transform in \c *p_transform. /// If \c p_gpr_ij is non-NULL, apply the transform to the metric \c *p_gpr_ij. /// /// \note \c *p_gpr_ij and \c *p_transform will be allocated if \c NULL. \c *p_gpr_ij and \c g_ij /// may point to the same matrix. /// int XLALDiagNormalizeMetric( gsl_matrix **p_gpr_ij, ///< [in,out,optional] Pointer to transformed matrix \f$g^{\prime}_{ij}\f$ gsl_matrix **p_transform, ///< [in,out,optional] Pointer to diagonal-normalization transform const gsl_matrix *g_ij ///< [in] Matrix to transform \f$g_{ij}\f$ ) { // Check input XLAL_CHECK( g_ij != NULL, XLAL_EFAULT ); XLAL_CHECK( g_ij->size1 == g_ij->size2, XLAL_ESIZE ); if ( p_transform != NULL ) { if ( *p_transform != NULL ) { XLAL_CHECK( (*p_transform)->size1 == g_ij->size1, XLAL_ESIZE ); XLAL_CHECK( (*p_transform)->size2 == g_ij->size2, XLAL_ESIZE ); } else { GAMAT( *p_transform, g_ij->size1, g_ij->size2 ); } } // Create diagonal normalization transform gsl_matrix *GAMAT( transform, g_ij->size1, g_ij->size2 ); gsl_matrix_set_zero( transform ); for ( size_t i = 0; i < g_ij->size1; ++i ) { const double gii = gsl_matrix_get(g_ij, i, i); XLAL_CHECK( gii > 0, XLAL_EINVAL, "Diagonal normalization not defined for non-positive diagonal elements! g_ii(%zu,%zu) = %g\n", i, i, gii ); gsl_matrix_set( transform, i, i, 1.0 / sqrt( gii ) ); } // Apply transform if ( p_gpr_ij != NULL ) { XLAL_CHECK( XLALTransformMetric( p_gpr_ij, transform, g_ij ) == XLAL_SUCCESS, XLAL_EFUNC ); } // Return transform if ( p_transform != NULL ) { gsl_matrix_memcpy( *p_transform, transform ); } // Cleanup GFMAT( transform ); return XLAL_SUCCESS; } // XLALDiagNormalizeMetric()
/// /// Compute the extent of the bounding box of the mismatch ellipse of a metric \f$ g_{ij} \f$. /// gsl_vector *XLALMetricEllipseBoundingBox( const gsl_matrix *g_ij, ///< [in] Parameter-space metric \f$ g_{ij} \f$ const double max_mismatch ///< [in] Maximum prescribed mismatch ) { // Check input XLAL_CHECK_NULL( g_ij != NULL, XLAL_EFAULT ); XLAL_CHECK_NULL( g_ij->size1 == g_ij->size2, XLAL_ESIZE ); const size_t n = g_ij->size1; // Allocate memory gsl_matrix *GAMAT_NULL( LU_decomp, n, n ); gsl_permutation *GAPERM_NULL( LU_perm, n ); gsl_matrix *GAMAT_NULL( diag_norm, n, n ); gsl_matrix *GAMAT_NULL( inverse, n, n ); gsl_vector *GAVEC_NULL( bounding_box, n ); // Diagonally normalize metric XLAL_CHECK_NULL( XLALDiagNormalizeMetric( &LU_decomp, &diag_norm, g_ij ) == XLAL_SUCCESS, XLAL_EFUNC ); // Compute metric inverse int LU_sign = 0; XLAL_CHECK_NULL( gsl_linalg_LU_decomp( LU_decomp, LU_perm, &LU_sign ) == 0, XLAL_EFAILED, "'g_ij' cannot be LU-decomposed" ); XLAL_CHECK_NULL( gsl_linalg_LU_invert( LU_decomp, LU_perm, inverse ) == 0, XLAL_EFAILED, "'g_ij' cannot be inverted" ); // Compute bounding box, and invert diagonal normalization for( size_t i = 0; i < n; ++i ) { const double diag_norm_i = gsl_matrix_get( diag_norm, i, i ); const double bounding_box_i = 2.0 * sqrt( max_mismatch * gsl_matrix_get( inverse, i, i ) ) * diag_norm_i; gsl_vector_set( bounding_box, i, bounding_box_i ); } // Cleanup GFMAT( LU_decomp, diag_norm, inverse ); GFPERM( LU_perm ); return bounding_box; } // XLALMetricEllipseBoundingBox()
/// /// Apply the inverse of a transform \f$\mathbf{A}^{-1} = \mathbf{B} = (b_{ij})\f$ to a metric /// \f$\mathbf{G} = (g_{ij})\f$ such that \f$ \mathbf{G} \rightarrow \mathbf{G}^{\prime} = /// \mathbf{B}^{\mathrm{T}} \mathbf{G} \mathbf{B} \f$, or equivalently \f$ g_{ij} \rightarrow /// g^{\prime}_{kl} = g_{ij} b_{ik} b_{jl} \f$. /// /// \note \c *p_gpr_ij will be allocated if \c NULL. \c *p_gpr_ij and \c g_ij may point to the same /// matrix. /// int XLALInverseTransformMetric( gsl_matrix **p_gpr_ij, ///< [in,out] Pointer to transformed matrix \f$\mathbf{G}^{\prime}\f$ const gsl_matrix *transform, ///< [in] Transform \f$\mathbf{A}\f$, the inverse of which to apply const gsl_matrix *g_ij ///< [in] Matrix to transform \f$\mathbf{G}\f$ ) { // Check input XLAL_CHECK( g_ij != NULL, XLAL_EFAULT ); XLAL_CHECK( transform != NULL, XLAL_EFAULT ); XLAL_CHECK( g_ij->size1 == g_ij->size2, XLAL_ESIZE ); XLAL_CHECK( g_ij->size2 == transform->size1, XLAL_ESIZE ); XLAL_CHECK( transform->size1 == transform->size2, XLAL_ESIZE ); XLAL_CHECK( p_gpr_ij != NULL, XLAL_EFAULT ); // Allocate memory gsl_matrix *GAMAT( LU_decomp, transform->size1, transform->size2 ); gsl_permutation *GAPERM( LU_perm, transform->size1 ); gsl_matrix *GAMAT( inverse, transform->size1, transform->size2 ); // Compute inverse of transform int LU_sign = 0; gsl_matrix_memcpy( LU_decomp, transform ); XLAL_CHECK( gsl_linalg_LU_decomp( LU_decomp, LU_perm, &LU_sign ) == 0, XLAL_EFAILED, "'transform' cannot be LU-decomposed" ); XLAL_CHECK( gsl_linalg_LU_invert( LU_decomp, LU_perm, inverse ) == 0, XLAL_EFAILED, "'transform' cannot be inverted" ); // Apply transform XLAL_CHECK( XLALTransformMetric( p_gpr_ij, inverse, g_ij ) == XLAL_SUCCESS, XLAL_EFUNC ); // Cleanup GFMAT( LU_decomp, inverse ); GFPERM( LU_perm ); return XLAL_SUCCESS; } // XLALInverseTransformMetric()
static int BasicTest( size_t n, const int bound_on_0, const int bound_on_1, const int bound_on_2, const int bound_on_3, const char *lattice_name, const UINT8 total_ref_0, const UINT8 total_ref_1, const UINT8 total_ref_2, const UINT8 total_ref_3 ) { const int bound_on[4] = {bound_on_0, bound_on_1, bound_on_2, bound_on_3}; const UINT8 total_ref[4] = {total_ref_0, total_ref_1, total_ref_2, total_ref_3}; // Create lattice tiling LatticeTiling *tiling = XLALCreateLatticeTiling(n); XLAL_CHECK(tiling != NULL, XLAL_EFUNC); // Add bounds for (size_t i = 0; i < n; ++i) { XLAL_CHECK(bound_on[i] == 0 || bound_on[i] == 1, XLAL_EFAILED); XLAL_CHECK(XLALSetLatticeTilingConstantBound(tiling, i, 0.0, bound_on[i] * pow(100.0, 1.0/n)) == XLAL_SUCCESS, XLAL_EFUNC); } // Set metric to the Lehmer matrix const double max_mismatch = 0.3; { gsl_matrix *GAMAT(metric, n, n); for (size_t i = 0; i < n; ++i) { for (size_t j = 0; j < n; ++j) { const double ii = i+1, jj = j+1; gsl_matrix_set(metric, i, j, jj >= ii ? ii/jj : jj/ii); } } XLAL_CHECK(XLALSetTilingLatticeAndMetric(tiling, lattice_name, metric, max_mismatch) == XLAL_SUCCESS, XLAL_EFUNC); GFMAT(metric); printf("Number of (tiled) dimensions: %zu (%zu)\n", XLALTotalLatticeTilingDimensions(tiling), XLALTiledLatticeTilingDimensions(tiling)); printf(" Bounds: %i %i %i %i\n", bound_on_0, bound_on_1, bound_on_2, bound_on_3); printf(" Lattice type: %s\n", lattice_name); } // Create lattice tiling locator LatticeTilingLocator *loc = XLALCreateLatticeTilingLocator(tiling); XLAL_CHECK(loc != NULL, XLAL_EFUNC); if (lalDebugLevel & LALINFOBIT) { printf(" Index trie:\n"); XLAL_CHECK(XLALPrintLatticeTilingIndexTrie(loc, stdout) == XLAL_SUCCESS, XLAL_EFUNC); } for (size_t i = 0; i < n; ++i) { // Create lattice tiling iterator and locator over 'i+1' dimensions LatticeTilingIterator *itr = XLALCreateLatticeTilingIterator(tiling, i+1); XLAL_CHECK(itr != NULL, XLAL_EFUNC); // Count number of points const UINT8 total = XLALTotalLatticeTilingPoints(itr); printf("Number of lattice points in %zu dimensions: %" LAL_UINT8_FORMAT "\n", i+1, total); XLAL_CHECK(imaxabs(total - total_ref[i]) <= 1, XLAL_EFUNC, "ERROR: |total - total_ref[%zu]| = |%" LAL_UINT8_FORMAT " - %" LAL_UINT8_FORMAT "| > 1", i, total, total_ref[i]); for (UINT8 k = 0; XLALNextLatticeTilingPoint(itr, NULL) > 0; ++k) { const UINT8 itr_index = XLALCurrentLatticeTilingIndex(itr); XLAL_CHECK(k == itr_index, XLAL_EFUNC, "ERROR: k = %" LAL_UINT8_FORMAT " != %" LAL_UINT8_FORMAT " = itr_index", k, itr_index); } XLAL_CHECK(XLALResetLatticeTilingIterator(itr) == XLAL_SUCCESS, XLAL_EFUNC); // Check tiling statistics printf(" Check tiling statistics ..."); for (size_t j = 0; j < n; ++j) { const LatticeTilingStats *stats = XLALLatticeTilingStatistics(tiling, j); XLAL_CHECK(stats != NULL, XLAL_EFUNC); XLAL_CHECK(imaxabs(stats->total_points - total_ref[j]) <= 1, XLAL_EFAILED, "\n " "ERROR: |total - total_ref[%zu]| = |%" LAL_UINT8_FORMAT " - %" LAL_UINT8_FORMAT "| > 1", j, stats->total_points, total_ref[j]); XLAL_CHECK(stats->min_points <= stats->avg_points, XLAL_EFAILED, "\n " "ERROR: min_points = %" LAL_INT4_FORMAT " > %g = avg_points", stats->min_points, stats->avg_points); XLAL_CHECK(stats->max_points >= stats->avg_points, XLAL_EFAILED, "\n " "ERROR: max_points = %" LAL_INT4_FORMAT " < %g = avg_points", stats->max_points, stats->avg_points); } printf(" done\n"); // Get all points gsl_matrix *GAMAT(points, n, total); XLAL_CHECK(XLALNextLatticeTilingPoints(itr, &points) == (int)total, XLAL_EFUNC); XLAL_CHECK(XLALNextLatticeTilingPoint(itr, NULL) == 0, XLAL_EFUNC); // Get nearest points to each template, check for consistency printf(" Testing XLALNearestLatticeTiling{Point|Block}() ..."); gsl_vector *GAVEC(nearest, n); UINT8Vector *nearest_indexes = XLALCreateUINT8Vector(n); XLAL_CHECK(nearest_indexes != NULL, XLAL_ENOMEM); for (UINT8 k = 0; k < total; ++k) { gsl_vector_const_view point_view = gsl_matrix_const_column(points, k); const gsl_vector *point = &point_view.vector; XLAL_CHECK(XLALNearestLatticeTilingPoint(loc, point, nearest, nearest_indexes) == XLAL_SUCCESS, XLAL_EFUNC); gsl_vector_sub(nearest, point); double err = gsl_blas_dasum(nearest) / n; XLAL_CHECK(err < 1e-6, XLAL_EFAILED, "\n " "ERROR: err = %e < 1e-6", err); XLAL_CHECK(nearest_indexes->data[i] == k, XLAL_EFAILED, "\n " "ERROR: nearest_indexes[%zu] = %" LAL_UINT8_FORMAT " != %" LAL_UINT8_FORMAT "\n", i, nearest_indexes->data[i], k); if (0 < i) { const LatticeTilingStats *stats = XLALLatticeTilingStatistics(tiling, i); UINT8 nearest_index = 0; UINT4 nearest_left = 0, nearest_right = 0; XLAL_CHECK(XLALNearestLatticeTilingBlock(loc, point, i, nearest, &nearest_index, &nearest_left, &nearest_right) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(nearest_index == nearest_indexes->data[i-1], XLAL_EFAILED, "\n " "ERROR: nearest_index = %" LAL_UINT8_FORMAT " != %" LAL_UINT8_FORMAT "\n", nearest_index, nearest_indexes->data[i-1]); UINT4 nearest_len = 1 + nearest_left + nearest_right; XLAL_CHECK(nearest_len <= stats->max_points, XLAL_EFAILED, "\n " "ERROR: nearest_len = %i > %i = stats[%zu]->max_points\n", nearest_len, stats->max_points, i); } if (i+1 < n) { const LatticeTilingStats *stats = XLALLatticeTilingStatistics(tiling, i+1); UINT8 nearest_index = 0; UINT4 nearest_left = 0, nearest_right = 0; XLAL_CHECK(XLALNearestLatticeTilingBlock(loc, point, i+1, nearest, &nearest_index, &nearest_left, &nearest_right) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(nearest_index == nearest_indexes->data[i], XLAL_EFAILED, "\n " "ERROR: nearest_index = %" LAL_UINT8_FORMAT " != %" LAL_UINT8_FORMAT "\n", nearest_index, nearest_indexes->data[i]); UINT4 nearest_len = 1 + nearest_left + nearest_right; XLAL_CHECK(nearest_len <= stats->max_points, XLAL_EFAILED, "\n " "ERROR: nearest_len = %i > %i = stats[%zu]->max_points\n", nearest_len, stats->max_points, i+1); } } printf(" done\n"); // Cleanup XLALDestroyLatticeTilingIterator(itr); GFMAT(points); GFVEC(nearest); XLALDestroyUINT8Vector(nearest_indexes); } for (size_t i = 0; i < n; ++i) { // Create alternating lattice tiling iterator over 'i+1' dimensions LatticeTilingIterator *itr_alt = XLALCreateLatticeTilingIterator(tiling, i+1); XLAL_CHECK(itr_alt != NULL, XLAL_EFUNC); XLAL_CHECK(XLALSetLatticeTilingAlternatingIterator(itr_alt, true) == XLAL_SUCCESS, XLAL_EFUNC); // Count number of points, check for consistency with non-alternating count UINT8 total = 0; while (XLALNextLatticeTilingPoint(itr_alt, NULL) > 0) ++total; XLAL_CHECK(imaxabs(total - total_ref[i]) <= 1, XLAL_EFUNC, "ERROR: alternating |total - total_ref[%zu]| = |%" LAL_UINT8_FORMAT " - %" LAL_UINT8_FORMAT "| > 1", i, total, total_ref[i]); // Cleanup XLALDestroyLatticeTilingIterator(itr_alt); } // Cleanup XLALDestroyLatticeTiling(tiling); XLALDestroyLatticeTilingLocator(loc); LALCheckMemoryLeaks(); printf("\n"); fflush(stdout); return XLAL_SUCCESS; }
static int SuperskyTest( const double T, const double max_mismatch, const char *lattice_name, const UINT8 patch_count, const double freq, const double freqband, const UINT8 total_ref, const double mism_hist_ref[MISM_HIST_BINS] ) { // Create lattice tiling LatticeTiling *tiling = XLALCreateLatticeTiling(3); XLAL_CHECK(tiling != NULL, XLAL_EFUNC); // Compute reduced supersky metric const double Tspan = T * 86400; LIGOTimeGPS ref_time; XLALGPSSetREAL8(&ref_time, 900100100); LALSegList segments; { XLAL_CHECK(XLALSegListInit(&segments) == XLAL_SUCCESS, XLAL_EFUNC); LALSeg segment; LIGOTimeGPS start_time = ref_time, end_time = ref_time; XLALGPSAdd(&start_time, -0.5 * Tspan); XLALGPSAdd(&end_time, 0.5 * Tspan); XLAL_CHECK(XLALSegSet(&segment, &start_time, &end_time, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(XLALSegListAppend(&segments, &segment) == XLAL_SUCCESS, XLAL_EFUNC); } MultiLALDetector detectors = { .length = 1, .sites = { lalCachedDetectors[LAL_LLO_4K_DETECTOR] } }; EphemerisData *edat = XLALInitBarycenter(TEST_DATA_DIR "earth00-19-DE405.dat.gz", TEST_DATA_DIR "sun00-19-DE405.dat.gz"); XLAL_CHECK(edat != NULL, XLAL_EFUNC); SuperskyMetrics *metrics = XLALComputeSuperskyMetrics(0, &ref_time, &segments, freq, &detectors, NULL, DETMOTION_SPIN | DETMOTION_PTOLEORBIT, edat); XLAL_CHECK(metrics != NULL, XLAL_EFUNC); gsl_matrix *rssky_metric = metrics->semi_rssky_metric, *rssky_transf = metrics->semi_rssky_transf; metrics->semi_rssky_metric = metrics->semi_rssky_transf = NULL; XLALDestroySuperskyMetrics(metrics); XLALSegListClear(&segments); XLALDestroyEphemerisData(edat); // Add bounds printf("Bounds: supersky, sky patch 0/%" LAL_UINT8_FORMAT ", freq=%0.3g, freqband=%0.3g\n", patch_count, freq, freqband); XLAL_CHECK(XLALSetSuperskyLatticeTilingPhysicalSkyPatch(tiling, rssky_metric, rssky_transf, patch_count, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(XLALSetSuperskyLatticeTilingPhysicalSpinBound(tiling, rssky_transf, 0, freq, freq + freqband) == XLAL_SUCCESS, XLAL_EFUNC); GFMAT(rssky_transf); // Set metric printf("Lattice type: %s\n", lattice_name); XLAL_CHECK(XLALSetTilingLatticeAndMetric(tiling, lattice_name, rssky_metric, max_mismatch) == XLAL_SUCCESS, XLAL_EFUNC); // Perform mismatch test XLAL_CHECK(MismatchTest(tiling, rssky_metric, max_mismatch, total_ref, mism_hist_ref) == XLAL_SUCCESS, XLAL_EFUNC); return XLAL_SUCCESS; } static int MultiSegSuperskyTest(void) { printf("Performing multiple-segment tests ...\n"); // Compute reduced supersky metrics const double Tspan = 86400; LIGOTimeGPS ref_time; XLALGPSSetREAL8(&ref_time, 900100100); LALSegList segments; { XLAL_CHECK(XLALSegListInit(&segments) == XLAL_SUCCESS, XLAL_EFUNC); LALSeg segment; { LIGOTimeGPS start_time = ref_time, end_time = ref_time; XLALGPSAdd(&start_time, -4 * Tspan); XLALGPSAdd(&end_time, -3 * Tspan); XLAL_CHECK(XLALSegSet(&segment, &start_time, &end_time, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(XLALSegListAppend(&segments, &segment) == XLAL_SUCCESS, XLAL_EFUNC); } { LIGOTimeGPS start_time = ref_time, end_time = ref_time; XLALGPSAdd(&start_time, -0.5 * Tspan); XLALGPSAdd(&end_time, 0.5 * Tspan); XLAL_CHECK(XLALSegSet(&segment, &start_time, &end_time, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(XLALSegListAppend(&segments, &segment) == XLAL_SUCCESS, XLAL_EFUNC); } { LIGOTimeGPS start_time = ref_time, end_time = ref_time; XLALGPSAdd(&start_time, 3.5 * Tspan); XLALGPSAdd(&end_time, 4.5 * Tspan); XLAL_CHECK(XLALSegSet(&segment, &start_time, &end_time, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(XLALSegListAppend(&segments, &segment) == XLAL_SUCCESS, XLAL_EFUNC); } } MultiLALDetector detectors = { .length = 1, .sites = { lalCachedDetectors[LAL_LLO_4K_DETECTOR] } }; EphemerisData *edat = XLALInitBarycenter(TEST_DATA_DIR "earth00-19-DE405.dat.gz", TEST_DATA_DIR "sun00-19-DE405.dat.gz"); XLAL_CHECK(edat != NULL, XLAL_EFUNC); SuperskyMetrics *metrics = XLALComputeSuperskyMetrics(1, &ref_time, &segments, 50, &detectors, NULL, DETMOTION_SPIN | DETMOTION_PTOLEORBIT, edat); XLAL_CHECK(metrics != NULL, XLAL_EFUNC); // Project and rescale semicoherent metric to give equal frequency spacings const double coh_max_mismatch = 0.2, semi_max_mismatch = 0.4; XLAL_CHECK(XLALEqualizeReducedSuperskyMetricsFreqSpacing(metrics, coh_max_mismatch, semi_max_mismatch) == XLAL_SUCCESS, XLAL_EFUNC); // Create lattice tilings LatticeTiling *coh_tiling[metrics->num_segments]; for (size_t n = 0; n < metrics->num_segments; ++n) { coh_tiling[n] = XLALCreateLatticeTiling(4); XLAL_CHECK(coh_tiling[n] != NULL, XLAL_EFUNC); } LatticeTiling *semi_tiling = XLALCreateLatticeTiling(4); XLAL_CHECK(semi_tiling != NULL, XLAL_EFUNC); // Add bounds for (size_t n = 0; n < metrics->num_segments; ++n) { XLAL_CHECK(XLALSetSuperskyLatticeTilingPhysicalSkyPatch(coh_tiling[n], metrics->coh_rssky_metric[n], metrics->coh_rssky_transf[n], 1, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(XLALSetSuperskyLatticeTilingPhysicalSpinBound(coh_tiling[n], metrics->coh_rssky_transf[n], 0, 50, 50 + 1e-4) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(XLALSetSuperskyLatticeTilingPhysicalSpinBound(coh_tiling[n], metrics->coh_rssky_transf[n], 1, 0, -5e-10) == XLAL_SUCCESS, XLAL_EFUNC); } XLAL_CHECK(XLALSetSuperskyLatticeTilingPhysicalSkyPatch(semi_tiling, metrics->semi_rssky_metric, metrics->semi_rssky_transf, 1, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(XLALSetSuperskyLatticeTilingPhysicalSpinBound(semi_tiling, metrics->semi_rssky_transf, 0, 50, 50 + 1e-4) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK(XLALSetSuperskyLatticeTilingPhysicalSpinBound(semi_tiling, metrics->semi_rssky_transf, 1, 0, -5e-10) == XLAL_SUCCESS, XLAL_EFUNC); // Set metric for (size_t n = 0; n < metrics->num_segments; ++n) { XLAL_CHECK(XLALSetTilingLatticeAndMetric(coh_tiling[n], "Ans", metrics->coh_rssky_metric[n], coh_max_mismatch) == XLAL_SUCCESS, XLAL_EFUNC); } XLAL_CHECK(XLALSetTilingLatticeAndMetric(semi_tiling, "Ans", metrics->semi_rssky_metric, semi_max_mismatch) == XLAL_SUCCESS, XLAL_EFUNC); // Check lattice step sizes in frequency const size_t ifreq = 3; const double semi_dfreq = XLALLatticeTilingStepSizes(semi_tiling, ifreq); for (size_t n = 0; n < metrics->num_segments; ++n) { const double coh_dfreq = XLALLatticeTilingStepSizes(coh_tiling[n], ifreq); const double tol = 1e-8; XLAL_CHECK(fabs(coh_dfreq - semi_dfreq) < tol * semi_dfreq, XLAL_EFAILED, " ERROR: semi_dfreq=%0.15e, coh_dfreq[%zu]=%0.15e, |coh_dfreq - semi_dfreq| >= %g * semi_dfreq", semi_dfreq, n, coh_dfreq, tol); } // Check computation of spindown range for coherent tilings for (size_t n = 0; n < metrics->num_segments; ++n) { PulsarSpinRange spin_range; XLAL_CHECK(XLALSuperskyLatticePulsarSpinRange(&spin_range, coh_tiling[n], metrics->coh_rssky_transf[n]) == XLAL_SUCCESS, XLAL_EFUNC); } // Cleanup for (size_t n = 0; n < metrics->num_segments; ++n) { XLALDestroyLatticeTiling(coh_tiling[n]); } XLALDestroyLatticeTiling(semi_tiling); XLALDestroySuperskyMetrics(metrics); XLALSegListClear(&segments); XLALDestroyEphemerisData(edat); LALCheckMemoryLeaks(); printf("\n"); fflush(stdout); return XLAL_SUCCESS; } int main(void) { // Perform basic tests XLAL_CHECK_MAIN(BasicTest(1, 0, 0, 0, 0, "Zn" , 1, 1, 1, 1) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(1, 1, 1, 1, 1, "Ans", 93, 0, 0, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(1, 1, 1, 1, 1, "Zn" , 93, 0, 0, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(2, 0, 0, 0, 0, "Ans", 1, 1, 1, 1) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(2, 1, 1, 1, 1, "Ans", 12, 144, 0, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(2, 1, 1, 1, 1, "Zn" , 13, 190, 0, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(3, 0, 0, 0, 0, "Zn" , 1, 1, 1, 1) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(3, 1, 1, 1, 1, "Ans", 8, 46, 332, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(3, 1, 1, 1, 1, "Zn" , 8, 60, 583, 0) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 0, 0, 0, 0, "Ans", 1, 1, 1, 1) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 0, 0, 0, 1, "Ans", 1, 1, 1, 4) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 0, 0, 1, 0, "Ans", 1, 1, 4, 4) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 0, 0, 1, 1, "Ans", 1, 1, 4, 20) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 0, 1, 0, 0, "Ans", 1, 4, 4, 4) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 0, 1, 0, 1, "Ans", 1, 5, 5, 25) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 0, 1, 1, 0, "Ans", 1, 5, 24, 24) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 0, 1, 1, 1, "Ans", 1, 5, 20, 115) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 1, 0, 0, 0, "Ans", 4, 4, 4, 4) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 1, 0, 0, 1, "Ans", 5, 5, 5, 23) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 1, 0, 1, 0, "Ans", 5, 5, 23, 23) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 1, 0, 1, 1, "Ans", 6, 6, 24, 139) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 1, 1, 0, 0, "Ans", 5, 25, 25, 25) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 1, 1, 0, 1, "Ans", 6, 30, 30, 162) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 1, 1, 1, 0, "Ans", 6, 27, 151, 151) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 1, 1, 1, 1, "Ans", 6, 30, 145, 897) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(BasicTest(4, 1, 1, 1, 1, "Zn" , 7, 46, 287, 2543) == XLAL_SUCCESS, XLAL_EFUNC); // Perform mismatch tests with a square parameter space XLAL_CHECK_MAIN(MismatchSquareTest("Zn", 0.03, 0, 0, 21460, Z1_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(MismatchSquareTest("Zn", 2e-4, -2e-9, 0, 23763, Z2_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(MismatchSquareTest("Zn", 1e-4, -1e-9, 1e-17, 19550, Z3_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(MismatchSquareTest("Ans", 0.03, 0, 0, 21460, A1s_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(MismatchSquareTest("Ans", 2e-4, -2e-9, 0, 18283, A2s_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(MismatchSquareTest("Ans", 1e-4, -2e-9, 2e-17, 20268, A3s_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); // Perform mismatch tests with an age--braking index parameter space XLAL_CHECK_MAIN(MismatchAgeBrakeTest("Ans", 100, 4.0e-5, 37872, A3s_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(MismatchAgeBrakeTest("Ans", 200, 1.5e-5, 37232, A3s_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(MismatchAgeBrakeTest("Ans", 300, 1.0e-5, 37022, A3s_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); // Perform mismatch tests with the reduced supersky parameter space and metric XLAL_CHECK_MAIN(SuperskyTest(1.1, 0.8, "Ans", 1, 50, 2.0e-5, 20548, A3s_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(SuperskyTest(1.5, 0.8, "Ans", 3, 50, 2.0e-5, 20202, A3s_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); XLAL_CHECK_MAIN(SuperskyTest(2.5, 0.8, "Ans", 17, 50, 2.0e-5, 29147, A3s_mism_hist) == XLAL_SUCCESS, XLAL_EFUNC); // Perform tests with the reduced supersky parameter space metric and multiple segments XLAL_CHECK_MAIN(MultiSegSuperskyTest() == XLAL_SUCCESS, XLAL_EFUNC); return EXIT_SUCCESS; }
static int MismatchTest( LatticeTiling *tiling, gsl_matrix *metric, const double max_mismatch, const UINT8 total_ref, const double mism_hist_ref[MISM_HIST_BINS] ) { const size_t n = XLALTotalLatticeTilingDimensions(tiling); // Create lattice tiling iterator and locator LatticeTilingIterator *itr = XLALCreateLatticeTilingIterator(tiling, n); XLAL_CHECK(itr != NULL, XLAL_EFUNC); LatticeTilingLocator *loc = XLALCreateLatticeTilingLocator(tiling); XLAL_CHECK(loc != NULL, XLAL_EFUNC); // Count number of points const UINT8 total = XLALTotalLatticeTilingPoints(itr); printf("Number of lattice points: %" LAL_UINT8_FORMAT "\n", total); XLAL_CHECK(imaxabs(total - total_ref) <= 1, XLAL_EFUNC, "ERROR: |total - total_ref| = |%" LAL_UINT8_FORMAT " - %" LAL_UINT8_FORMAT "| > 1", total, total_ref); // Get all points gsl_matrix *GAMAT(points, n, total); XLAL_CHECK(XLALNextLatticeTilingPoints(itr, &points) == (int)total, XLAL_EFUNC); XLAL_CHECK(XLALNextLatticeTilingPoint(itr, NULL) == 0, XLAL_EFUNC); // Initialise mismatch histogram counts double mism_hist[MISM_HIST_BINS] = {0}; double mism_hist_total = 0, mism_hist_out_of_range = 0; // Perform 10 injections for every template { gsl_matrix *GAMAT(injections, 3, total); gsl_matrix *GAMAT(nearest, 3, total); gsl_matrix *GAMAT(temp, 3, total); RandomParams *rng = XLALCreateRandomParams(total); XLAL_CHECK(rng != NULL, XLAL_EFUNC); for (size_t i = 0; i < 10; ++i) { // Generate random injection points XLAL_CHECK(XLALRandomLatticeTilingPoints(tiling, 0.0, rng, injections) == XLAL_SUCCESS, XLAL_EFUNC); // Find nearest lattice template points XLAL_CHECK(XLALNearestLatticeTilingPoints(loc, injections, &nearest, NULL) == XLAL_SUCCESS, XLAL_EFUNC); // Compute mismatch between injections gsl_matrix_sub(nearest, injections); gsl_blas_dsymm(CblasLeft, CblasUpper, 1.0, metric, nearest, 0.0, temp); for (size_t j = 0; j < temp->size2; ++j) { gsl_vector_view temp_j = gsl_matrix_column(temp, j); gsl_vector_view nearest_j = gsl_matrix_column(nearest, j); double mismatch = 0.0; gsl_blas_ddot(&nearest_j.vector, &temp_j.vector, &mismatch); mismatch /= max_mismatch; // Increment mismatch histogram counts ++mism_hist_total; if (mismatch < 0.0 || mismatch > 1.0) { ++mism_hist_out_of_range; } else { ++mism_hist[lround(floor(mismatch * MISM_HIST_BINS))]; } } } // Cleanup GFMAT(injections, nearest, temp); XLALDestroyRandomParams(rng); } // Normalise histogram for (size_t i = 0; i < MISM_HIST_BINS; ++i) { mism_hist[i] *= MISM_HIST_BINS / mism_hist_total; } // Print mismatch histogram and its reference printf("Mismatch histogram: "); for (size_t i = 0; i < MISM_HIST_BINS; ++i) { printf(" %0.3f", mism_hist[i]); } printf("\n"); printf("Reference histogram:"); for (size_t i = 0; i < MISM_HIST_BINS; ++i) { printf(" %0.3f", mism_hist_ref[i]); } printf("\n"); // Determine error between mismatch histogram and its reference double mism_hist_error = 0.0; for (size_t i = 0; i < MISM_HIST_BINS; ++i) { mism_hist_error += fabs(mism_hist[i] - mism_hist_ref[i]); } mism_hist_error /= MISM_HIST_BINS; printf("Mismatch histogram error: %0.3e\n", mism_hist_error); const double mism_hist_error_tol = 5e-2; if (mism_hist_error >= mism_hist_error_tol) { XLAL_ERROR(XLAL_EFAILED, "ERROR: mismatch histogram error exceeds %0.3e\n", mism_hist_error_tol); } // Check fraction of injections out of histogram range const double mism_out_of_range = mism_hist_out_of_range / mism_hist_total; printf("Fraction of points out of histogram range: %0.3e\n", mism_out_of_range); const double mism_out_of_range_tol = 2e-3; if (mism_out_of_range > mism_out_of_range_tol) { XLAL_ERROR(XLAL_EFAILED, "ERROR: fraction of points out of histogram range exceeds %0.3e\n", mism_out_of_range_tol); } // Perform 10 injections outside parameter space { gsl_matrix *GAMAT(injections, 3, 10); gsl_matrix *GAMAT(nearest, n, total); RandomParams *rng = XLALCreateRandomParams(total); XLAL_CHECK(rng != NULL, XLAL_EFUNC); // Generate random injection points outside parameter space XLAL_CHECK(XLALRandomLatticeTilingPoints(tiling, 5.0, rng, injections) == XLAL_SUCCESS, XLAL_EFUNC); // Find nearest lattice template points XLAL_CHECK(XLALNearestLatticeTilingPoints(loc, injections, &nearest, NULL) == XLAL_SUCCESS, XLAL_EFUNC); // Cleanup GFMAT(injections, nearest); XLALDestroyRandomParams(rng); } // Cleanup XLALDestroyLatticeTiling(tiling); XLALDestroyLatticeTilingIterator(itr); XLALDestroyLatticeTilingLocator(loc); GFMAT(metric, points); LALCheckMemoryLeaks(); printf("\n"); fflush(stdout); return XLAL_SUCCESS; }
/// /// Compute the transform which changes the metric reference time \f$ \tau_0 \rightarrow \tau_1 = /// \tau_0 + \Delta\tau \f$. /// /// If \c p_transform is non-NULL, return the reference-time transform in \c *p_transform. /// If \c p_gpr_ij is non-NULL, apply the transform to the metric \c *p_gpr_ij. /// /// \note \c *p_gpr_ij and \c *p_transform will be allocated if \c NULL. \c *p_gpr_ij and \c g_ij /// may point to the same matrix. /// int XLALChangeMetricReferenceTime( gsl_matrix **p_gpr_ij, ///< [in,out,optional] Pointer to transformed matrix \f$g^{\prime}_{ij}\f$ gsl_matrix **p_transform, ///< [in,out,optional] Pointer to reference time transform const gsl_matrix *g_ij, ///< [in] Matrix to transform \f$g_{ij}\f$ const DopplerCoordinateSystem *coordSys, ///< [in] Coordinate system of metric const double Dtau ///< [in] Difference between new and old reference times \f$\Delta\tau\f$ ) { // Check input XLAL_CHECK( g_ij != NULL, XLAL_EFAULT ); XLAL_CHECK( g_ij->size1 == g_ij->size2, XLAL_ESIZE ); if ( p_transform != NULL ) { if ( *p_transform != NULL ) { XLAL_CHECK( (*p_transform)->size1 == g_ij->size1, XLAL_ESIZE ); XLAL_CHECK( (*p_transform)->size2 == g_ij->size2, XLAL_ESIZE ); } else { GAMAT( *p_transform, g_ij->size1, g_ij->size2 ); } } XLAL_CHECK( coordSys != NULL, XLAL_EFAULT ); XLAL_CHECK( coordSys->dim == g_ij->size1, XLAL_ESIZE ); for( size_t i = 0; i < coordSys->dim; ++i ) { switch( coordSys->coordIDs[i] ) { case DOPPLERCOORD_GC_NU0: case DOPPLERCOORD_GC_NU1: case DOPPLERCOORD_GC_NU2: case DOPPLERCOORD_GC_NU3: XLAL_ERROR( XLAL_EINVAL, "GCT coordinates are not supported" ); default: break; } } // Compute transformation matrix for frequency-spindown coordinates // from Prix: "Frequency metric for CW searches" (2014-08-17), p. 4 gsl_matrix *GAMAT( transform, g_ij->size1, g_ij->size2 ); gsl_matrix_set_identity( transform ); if( Dtau != 0.0 ) { for( size_t i = 0; i < coordSys->dim; ++i ) { const DopplerCoordinateID icoord = coordSys->coordIDs[i]; if (DOPPLERCOORD_FREQ <= icoord && icoord <= DOPPLERCOORD_LASTFDOT) { const size_t ispinorder = icoord - DOPPLERCOORD_FREQ; for( size_t j = i + 1; j < coordSys->dim; ++j ) { const DopplerCoordinateID jcoord = coordSys->coordIDs[j]; if (DOPPLERCOORD_FREQ <= jcoord && jcoord <= DOPPLERCOORD_LASTFDOT) { const size_t jspinorder = jcoord - DOPPLERCOORD_FREQ; if( jspinorder > ispinorder ) { const double tij = LAL_FACT_INV[jspinorder - ispinorder] * pow( -1 * Dtau, jspinorder - ispinorder ); gsl_matrix_set( transform, i, j, tij ); } } } } } } // Apply transform if ( p_gpr_ij != NULL ) { XLAL_CHECK( XLALTransformMetric( p_gpr_ij, transform, g_ij ) == XLAL_SUCCESS, XLAL_EFUNC ); } // Return transform if ( p_transform != NULL ) { gsl_matrix_memcpy( *p_transform, transform ); } // Cleanup GFMAT( transform ); return XLAL_SUCCESS; } // XLALPhaseMetricRefTimeTransform()
/// /// Return a metric in <i>naturalized</i> coordinates. /// Frequency coordinates of spindown order \f$s\f$ are scaled by /// \f[ \frac{2\pi}{(s+1)!} \left(\frac{\overline{\Delta T}}{2}\right)^{s+1} \f] /// where \f$\overline{\Delta T}\equiv\sum_{k}^{N} \Delta T_k\f$ is the average segment-length /// over all \f$N\f$ segments. /// /// Sky coordinates are scaled by Holgers' units, see Eq.(44) in PRD82,042002(2010), /// without the equatorial rotation in alpha: /// \f[ \frac{2\pi f R_{E} \cos(\delta_{D})}{c} \f] /// where \f$f\f$ is the frequency and /// \f$R_{E}\f$ the Earth radius, and \f$\delta_{D}\f$ is the detectors latitude. /// /// If \c p_transform is non-NULL, return the naturalization transform in \c *p_transform. /// If \c p_gpr_ij is non-NULL, apply the transform to the metric \c *p_gpr_ij. /// /// \note \c *p_gpr_ij and \c *p_transform will be allocated if \c NULL. \c *p_gpr_ij and \c g_ij /// may point to the same matrix. /// int XLALNaturalizeMetric( gsl_matrix **p_gpr_ij, ///< [in,out,optional] Pointer to transformed matrix \f$g^{\prime}_{ij}\f$ gsl_matrix **p_transform, ///< [in,out,optional] Pointer to naturalization transform const gsl_matrix *g_ij, ///< [in] Matrix to transform \f$g_{ij}\f$ const DopplerMetricParams *metricParams ///< [in] Input parameters used to calculate naturalization transform ) { // Check input XLAL_CHECK( g_ij != NULL, XLAL_EFAULT ); XLAL_CHECK( g_ij->size1 == g_ij->size2, XLAL_ESIZE ); if ( p_transform != NULL ) { if ( *p_transform != NULL ) { XLAL_CHECK( (*p_transform)->size1 == g_ij->size1, XLAL_ESIZE ); XLAL_CHECK( (*p_transform)->size2 == g_ij->size2, XLAL_ESIZE ); } else { GAMAT( *p_transform, g_ij->size1, g_ij->size2 ); } } XLAL_CHECK( metricParams != NULL, XLAL_EFAULT ); // Compute average segment length XLAL_CHECK ( XLALSegListIsInitialized ( &(metricParams->segmentList) ), XLAL_EINVAL, "Passed un-initialzied segment list 'metricParams->segmentList'\n"); UINT4 Nseg = metricParams->segmentList.length; REAL8 sumTseg = 0; for ( UINT4 k=0; k < Nseg; k ++ ) { LIGOTimeGPS *startTime_k = &(metricParams->segmentList.segs[k].start); LIGOTimeGPS *endTime_k = &(metricParams->segmentList.segs[k].end); sumTseg += XLALGPSDiff( endTime_k, startTime_k ); } REAL8 avgTseg = sumTseg / Nseg; // Compute naturalization transform gsl_matrix *GAMAT( transform, g_ij->size1, g_ij->size2 ); gsl_matrix_set_zero( transform ); for (size_t i = 0; i < g_ij->size1; ++i) { const DopplerCoordinateID coordID = metricParams->coordSys.coordIDs[i]; const double Freq = metricParams->signalParams.Doppler.fkdot[0]; const double T = avgTseg; double scale = 0; switch (coordID) { case DOPPLERCOORD_NONE: scale = 1; break; case DOPPLERCOORD_FREQ: case DOPPLERCOORD_GC_NU0: scale = LAL_TWOPI * LAL_FACT_INV[1] * (0.5 * T); break; case DOPPLERCOORD_F1DOT: case DOPPLERCOORD_GC_NU1: scale = LAL_TWOPI * LAL_FACT_INV[2] * POW2(0.5 * T); break; case DOPPLERCOORD_F2DOT: case DOPPLERCOORD_GC_NU2: scale = LAL_TWOPI * LAL_FACT_INV[3] * POW3(0.5 * T); break; case DOPPLERCOORD_F3DOT: case DOPPLERCOORD_GC_NU3: scale = LAL_TWOPI * LAL_FACT_INV[4] * POW4(0.5 * T); break; case DOPPLERCOORD_ALPHA: case DOPPLERCOORD_DELTA: case DOPPLERCOORD_N2X_EQU: case DOPPLERCOORD_N2Y_EQU: case DOPPLERCOORD_N2X_ECL: case DOPPLERCOORD_N2Y_ECL: case DOPPLERCOORD_N3X_EQU: case DOPPLERCOORD_N3Y_EQU: case DOPPLERCOORD_N3Z_EQU: case DOPPLERCOORD_N3X_ECL: case DOPPLERCOORD_N3Y_ECL: case DOPPLERCOORD_N3Z_ECL: case DOPPLERCOORD_N3SX_EQU: case DOPPLERCOORD_N3SY_EQU: case DOPPLERCOORD_N3OX_ECL: case DOPPLERCOORD_N3OY_ECL: { const REAL8 rEarth_c = (LAL_REARTH_SI / LAL_C_SI); REAL8 cosdD = cos ( metricParams->multiIFO.sites[0].frDetector.vertexLatitudeRadians ); scale = LAL_TWOPI * Freq * rEarth_c * cosdD; } break; default: scale = 1; break; } // switch(coordID) gsl_matrix_set( transform, i, i, 1.0 / scale ); } // Apply transform if ( p_gpr_ij != NULL ) { XLAL_CHECK( XLALTransformMetric( p_gpr_ij, transform, g_ij ) == XLAL_SUCCESS, XLAL_EFUNC ); } // Return transform if ( p_transform != NULL ) { gsl_matrix_memcpy( *p_transform, transform ); } // Cleanup GFMAT( transform ); return XLAL_SUCCESS; } // XLALNaturalizeMetric()
static int CheckSuperskyMetrics( const gsl_matrix *rssky_metric, const double rssky_metric_ref[4][4], const gsl_matrix *rssky_transf, const double rssky_transf_ref[6][3], const double phys_mismatch[NUM_POINTS][NUM_POINTS], const double phys_mismatch_tol ) { // Check supersky metrics { gsl_matrix_const_view rssky_metric_ref_view = gsl_matrix_const_view_array( ( const double * )rssky_metric_ref, 4, 4 ); const double err = XLALCompareMetrics( rssky_metric, &rssky_metric_ref_view.matrix ), err_tol = 1e-6; XLAL_CHECK( err <= err_tol, XLAL_ETOL, "'rssky_metric' check failed: err = %0.3e > %0.3e = err_tol", err, err_tol ); } { XLAL_CHECK( rssky_transf->size1 == 6 && rssky_transf->size2 == 3, XLAL_ESIZE ); const double err_tol = 1e-5; for ( size_t i = 0; i < rssky_transf->size1; ++i ) { for ( size_t j = 0; j < rssky_transf->size2; ++j ) { const double rssky_transf_ij = gsl_matrix_get( rssky_transf, i, j ); const double rssky_transf_ref_ij = rssky_transf_ref[i][j]; CHECK_RELERR( rssky_transf_ij, rssky_transf_ref_ij, err_tol ); } } } // Check round-trip conversions of each test point { gsl_matrix *GAMAT( rssky_points, 4, NUM_POINTS ); for ( size_t j = 0; j < NUM_POINTS; ++j ) { gsl_vector_view rssky_point = gsl_matrix_column( rssky_points, j ); PulsarDopplerParams XLAL_INIT_DECL( new_phys_point ); XLAL_CHECK( XLALConvertPhysicalToSuperskyPoint( &rssky_point.vector, &phys_points[j], rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK( XLALConvertSuperskyToPhysicalPoint( &new_phys_point, &rssky_point.vector, rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK( CompareDoppler( &phys_points[j], &new_phys_point ) == EXIT_SUCCESS, XLAL_EFUNC ); } gsl_matrix *intm_phys_points = NULL; gsl_matrix *new_rssky_points = NULL; XLAL_CHECK( XLALConvertSuperskyToPhysicalPoints( &intm_phys_points, rssky_points, rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC ); XLAL_CHECK( XLALConvertPhysicalToSuperskyPoints( &new_rssky_points, intm_phys_points, rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC ); const double err_tol = 1e-6; for ( size_t i = 0; i < 4; ++i ) { for ( size_t j = 0; j < NUM_POINTS; ++j ) { const double rssky_points_ij = gsl_matrix_get( rssky_points, i, j ); const double new_rssky_points_ij = gsl_matrix_get( new_rssky_points, i, j ); CHECK_RELERR( rssky_points_ij, new_rssky_points_ij, err_tol ); } } GFMAT( rssky_points, intm_phys_points, new_rssky_points ); } // Check mismatches between pairs of points { gsl_vector *GAVEC( rssky_point_i, 4 ); gsl_vector *GAVEC( rssky_point_j, 4 ); gsl_vector *GAVEC( temp, 4 ); for ( size_t i = 0; i < NUM_POINTS; ++i ) { XLAL_CHECK( XLALConvertPhysicalToSuperskyPoint( rssky_point_i, &phys_points[i], rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC ); for ( size_t j = 0; j < NUM_POINTS; ++j ) { XLAL_CHECK( XLALConvertPhysicalToSuperskyPoint( rssky_point_j, &phys_points[j], rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC ); gsl_vector_sub( rssky_point_j, rssky_point_i ); gsl_blas_dgemv( CblasNoTrans, 1.0, rssky_metric, rssky_point_j, 0.0, temp ); double mismatch = 0.0; gsl_blas_ddot( rssky_point_j, temp, &mismatch ); CHECK_RELERR( mismatch, phys_mismatch[i][j], phys_mismatch_tol ); } } GFVEC( rssky_point_i, rssky_point_j, temp ); } return XLAL_SUCCESS; }