void progressbar_settext(char * buf, int iter, int pbar_maxval, int nlive_points, int ndraws, double logZ, double remainderZ, double logZerr, double remainderZerr, point * current, int ndim) { int i; int n = sprintf(buf, "|%d/%d samples+%d/%d|lnZ = %.2f +- %.3f + %.3f|L=%.2e @ ", iter + 1, pbar_maxval, nlive_points, ndraws, logaddexp(logZ, remainderZ), logZerr, remainderZerr, current->L); for(i = 0; i < ndim && n < 200; i++) { n += sprintf(buf + n, "%.3e ", current->phys_coords[i]); } }
JNI_METHOD(void, unsafeLogAddExp)(JNIEnv *env, jobject, jdoubleArray jsrc1, jint src_offset1, jdoubleArray jsrc2, jint src_offset2, jdoubleArray jdst, jint dst_offset, jint length) { jdouble *src1 = reinterpret_cast<jdouble *>( env->GetPrimitiveArrayCritical(jsrc1, NULL)); jdouble *src2 = reinterpret_cast<jdouble *>( env->GetPrimitiveArrayCritical(jsrc2, NULL)); jdouble *dst = reinterpret_cast<jdouble *>( env->GetPrimitiveArrayCritical(jdst, NULL)); boost::simd::transform(src1 + src_offset1, src1 + src_offset1 + length, src2 + src_offset2, dst + dst_offset, logaddexp()); env->ReleasePrimitiveArrayCritical(jsrc1, src1, JNI_ABORT); env->ReleasePrimitiveArrayCritical(jsrc2, src2, JNI_ABORT); env->ReleasePrimitiveArrayCritical(jdst, dst, JNI_ABORT); }
double *bayestar_sky_map_toa_phoa_snr( long *npix, /* Input: number of HEALPix pixels. */ double gmst, /* Greenwich mean sidereal time in radians. */ int nifos, /* Input: number of detectors. */ const float (**responses)[3], /* Pointers to detector responses. */ const double **locations, /* Pointers to locations of detectors in Cartesian geographic coordinates. */ const double *toas, /* Input: array of times of arrival with arbitrary relative offset. (Make toas[0] == 0.) */ const double *phoas, /* Input: array of phases of arrival with arbitrary relative offset. (Make phoas[0] == 0.) */ const double *snrs, /* Input: array of SNRs. */ const double *w_toas, /* Input: sum-of-squares weights, (1/TOA variance)^2. */ const double *w1s, /* Input: first moments of angular frequency. */ const double *w2s, /* Input: second moments of angular frequency. */ const double *horizons, /* Distances at which a source would produce an SNR of 1 in each detector. */ double min_distance, double max_distance, int prior_distance_power) /* Use a prior of (distance)^(prior_distance_power) */ { long nside; long maxpix; long i; double d1[nifos]; double *P; gsl_permutation *pix_perm; double complex exp_i_phoas[nifos]; /* Hold GSL return values for any thread that fails. */ int gsl_errno = GSL_SUCCESS; /* Storage for old GSL error handler. */ gsl_error_handler_t *old_handler; /* Maximum number of subdivisions for adaptive integration. */ static const size_t subdivision_limit = 64; /* Subdivide radial integral where likelihood is this fraction of the maximum, * will be used in solving the quadratic to find the breakpoints */ static const double eta = 0.01; /* Use this many integration steps in 2*psi */ static const int ntwopsi = 16; /* Number of integration steps in cos(inclination) */ static const int nu = 16; /* Number of integration steps in arrival time */ static const int nt = 16; /* Rescale distances so that furthest horizon distance is 1. */ { double d1max; memcpy(d1, horizons, sizeof(d1)); for (d1max = d1[0], i = 1; i < nifos; i ++) if (d1[i] > d1max) d1max = d1[i]; for (i = 0; i < nifos; i ++) d1[i] /= d1max; min_distance /= d1max; max_distance /= d1max; } (void)w2s; /* FIXME: remove unused parameter */ for (i = 0; i < nifos; i ++) exp_i_phoas[i] = exp_i(phoas[i]); /* Evaluate posterior term only first. */ P = bayestar_sky_map_toa_adapt_resolution(&pix_perm, &maxpix, npix, gmst, nifos, locations, toas, w_toas, autoresolution_count_pix_toa_phoa_snr); if (!P) return NULL; /* Determine the lateral HEALPix resolution. */ nside = npix2nside(*npix); /* Zero all pixels that didn't meet the TDOA cut. */ for (i = maxpix; i < *npix; i ++) { long ipix = gsl_permutation_get(pix_perm, i); P[ipix] = -INFINITY; } /* Use our own error handler while in parallel section to avoid concurrent * calls to the GSL error handler, which if provided by the user may not * be threadsafe. */ old_handler = gsl_set_error_handler(my_gsl_error); /* Compute posterior factor for amplitude consistency. */ #pragma omp parallel for firstprivate(gsl_errno) lastprivate(gsl_errno) for (i = 0; i < maxpix; i ++) { /* Cancel further computation if a GSL error condition has occurred. * * Note: if one thread sets gsl_errno, not necessarily all thread will * get the updated value. That's OK, because most failure modes will * cause GSL error conditions on all threads. If we cared to have any * failure on any thread terminate all of the other threads as quickly * as possible, then we would want to insert the following pragma here: * * #pragma omp flush(gsl_errno) * * and likewise before any point where we set gsl_errno. */ if (gsl_errno != GSL_SUCCESS) goto skip; { long ipix = gsl_permutation_get(pix_perm, i); double complex F[nifos]; double theta, phi; int itwopsi, iu, it, iifo; double accum = -INFINITY; double complex exp_i_toaphoa[nifos]; double dtau[nifos], mean_dtau; /* Prepare workspace for adaptive integrator. */ gsl_integration_workspace *workspace = gsl_integration_workspace_alloc(subdivision_limit); /* If the workspace could not be allocated, then record the GSL * error value for later reporting when we leave the parallel * section. Then, skip to the next loop iteration. */ if (!workspace) { gsl_errno = GSL_ENOMEM; goto skip; } /* Look up polar coordinates of this pixel */ pix2ang_ring(nside, ipix, &theta, &phi); toa_errors(dtau, theta, phi, gmst, nifos, locations, toas); for (iifo = 0; iifo < nifos; iifo ++) exp_i_toaphoa[iifo] = exp_i_phoas[iifo] * exp_i(w1s[iifo] * dtau[iifo]); /* Find mean arrival time error */ mean_dtau = gsl_stats_wmean(w_toas, 1, dtau, 1, nifos); /* Look up antenna factors */ for (iifo = 0; iifo < nifos; iifo++) { XLALComputeDetAMResponse( (double *)&F[iifo], /* Type-punned real part */ 1 + (double *)&F[iifo], /* Type-punned imag part */ responses[iifo], phi, M_PI_2 - theta, 0, gmst); F[iifo] *= d1[iifo]; } /* Integrate over 2*psi */ for (itwopsi = 0; itwopsi < ntwopsi; itwopsi++) { const double twopsi = (2 * M_PI / ntwopsi) * itwopsi; const double complex exp_i_twopsi = exp_i(twopsi); /* Integrate over u from u=-1 to u=1. */ for (iu = -nu; iu <= nu; iu++) { const double u = (double)iu / nu; const double u2 = gsl_pow_2(u); double A = 0, B = 0; double breakpoints[5]; int num_breakpoints = 0; double log_offset = -INFINITY; /* The log-likelihood is quadratic in the estimated and true * values of the SNR, and in 1/r. It is of the form A/r^2 + B/r, * where A depends only on the true values of the SNR and is * strictly negative and B depends on both the true values and * the estimates and is strictly positive. * * The middle breakpoint is at the maximum of the log-likelihood, * occurring at 1/r=-B/2A. The lower and upper breakpoints occur * when the likelihood becomes eta times its maximum value. This * occurs when * * A/r^2 + B/r = log(eta) - B^2/4A. * */ /* Perform arrival time integral */ double accum1 = -INFINITY; for (it = -nt/2; it <= nt/2; it++) { const double t = mean_dtau + LAL_REARTH_SI / LAL_C_SI * it / nt; double complex i0arg_complex = 0; for (iifo = 0; iifo < nifos; iifo++) { const double complex tmp = F[iifo] * exp_i_twopsi; /* FIXME: could use - sign here to avoid conj below, but * this probably just sets our sign convention relative to * detection pipeline */ double complex phase_rhotimesr = 0.5 * (1 + u2) * creal(tmp) + I * u * cimag(tmp); const double abs_rhotimesr_2 = cabs2(phase_rhotimesr); const double abs_rhotimesr = sqrt(abs_rhotimesr_2); phase_rhotimesr /= abs_rhotimesr; i0arg_complex += exp_i_toaphoa[iifo] * exp_i(-w1s[iifo] * t) * phase_rhotimesr * gsl_pow_2(snrs[iifo]); } const double i0arg = cabs(i0arg_complex); accum1 = logaddexp(accum1, log(gsl_sf_bessel_I0_scaled(i0arg)) + i0arg - 0.5 * gsl_stats_wtss_m(w_toas, 1, dtau, 1, nifos, t)); } /* Loop over detectors */ for (iifo = 0; iifo < nifos; iifo++) { const double complex tmp = F[iifo] * exp_i_twopsi; /* FIXME: could use - sign here to avoid conj below, but * this probably just sets our sign convention relative to * detection pipeline */ double complex phase_rhotimesr = 0.5 * (1 + u2) * creal(tmp) + I * u * cimag(tmp); const double abs_rhotimesr_2 = cabs2(phase_rhotimesr); const double abs_rhotimesr = sqrt(abs_rhotimesr_2); A += abs_rhotimesr_2; B += abs_rhotimesr * snrs[iifo]; } A *= -0.5; { const double middle_breakpoint = -2 * A / B; const double lower_breakpoint = 1 / (1 / middle_breakpoint + sqrt(log(eta) / A)); const double upper_breakpoint = 1 / (1 / middle_breakpoint - sqrt(log(eta) / A)); breakpoints[num_breakpoints++] = min_distance; if(lower_breakpoint > breakpoints[num_breakpoints-1] && lower_breakpoint < max_distance) breakpoints[num_breakpoints++] = lower_breakpoint; if(middle_breakpoint > breakpoints[num_breakpoints-1] && middle_breakpoint < max_distance) breakpoints[num_breakpoints++] = middle_breakpoint; if(upper_breakpoint > breakpoints[num_breakpoints-1] && upper_breakpoint < max_distance) breakpoints[num_breakpoints++] = upper_breakpoint; breakpoints[num_breakpoints++] = max_distance; } { /* * Set log_offset to the maximum of the logarithm of the * radial integrand evaluated at all of the breakpoints. */ int ibreakpoint; for (ibreakpoint = 0; ibreakpoint < num_breakpoints; ibreakpoint++) { const double new_log_offset = log_radial_integrand( breakpoints[ibreakpoint], A, B, prior_distance_power); if (new_log_offset < INFINITY && new_log_offset > log_offset) log_offset = new_log_offset; } } { /* Perform adaptive integration. Stop when a relative * accuracy of 0.05 has been reached. */ inner_integrand_params integrand_params = {A, B, log_offset, prior_distance_power}; const gsl_function func = {radial_integrand, &integrand_params}; double result, abserr; int ret = gsl_integration_qagp(&func, &breakpoints[0], num_breakpoints, DBL_MIN, 0.05, subdivision_limit, workspace, &result, &abserr); /* If the integrator failed, then record the GSL error * value for later reporting when we leave the parallel * section. Then, break out of the loop. */ if (ret != GSL_SUCCESS) { gsl_errno = ret; gsl_integration_workspace_free(workspace); goto skip; } /* Take the logarithm and put the log-normalization back in. */ result = log(result) + integrand_params.log_offset + accum1; /* Accumulate result. */ accum = logaddexp(accum, result); } } } /* Discard workspace for adaptive integrator. */ gsl_integration_workspace_free(workspace); /* Store log posterior. */ P[ipix] = accum; } skip: /* this statement intentionally left blank */; } /* Restore old error handler. */ gsl_set_error_handler(old_handler); /* Free permutation. */ gsl_permutation_free(pix_perm); /* Check if there was an error in any thread evaluating any pixel. If there * was, raise the error and return. */ if (gsl_errno != GSL_SUCCESS) { free(P); GSL_ERROR_NULL(gsl_strerror(gsl_errno), gsl_errno); } /* Exponentiate and normalize posterior. */ pix_perm = get_pixel_ranks(*npix, P); if (!pix_perm) { free(P); return NULL; } exp_normalize(*npix, P, pix_perm); gsl_permutation_free(pix_perm); return P; }
double *bayestar_sky_map_toa_snr( long *npix, /* Input: number of HEALPix pixels. */ double gmst, /* Greenwich mean sidereal time in radians. */ int nifos, /* Input: number of detectors. */ const float (**responses)[3], /* Pointers to detector responses. */ const double **locations, /* Pointers to locations of detectors in Cartesian geographic coordinates. */ const double *toas, /* Input: array of times of arrival with arbitrary relative offset. (Make toas[0] == 0.) */ const double *snrs, /* Input: array of SNRs. */ const double *w_toas, /* Input: sum-of-squares weights, (1/TOA variance)^2. */ const double *horizons, /* Distances at which a source would produce an SNR of 1 in each detector. */ double min_distance, double max_distance, int prior_distance_power) /* Use a prior of (distance)^(prior_distance_power) */ { long nside; long maxpix; long i; double d1[nifos]; double *P; gsl_permutation *pix_perm; /* Hold GSL return values for any thread that fails. */ int gsl_errno = GSL_SUCCESS; /* Storage for old GSL error handler. */ gsl_error_handler_t *old_handler; /* Maximum number of subdivisions for adaptive integration. */ static const size_t subdivision_limit = 64; /* Subdivide radial integral where likelihood is this fraction of the maximum, * will be used in solving the quadratic to find the breakpoints */ static const double eta = 0.01; /* Use this many integration steps in 2*psi */ static const int ntwopsi = 16; /* Number of integration steps in cos(inclination) */ static const int nu = 16; /* Rescale distances so that furthest horizon distance is 1. */ { double d1max; memcpy(d1, horizons, sizeof(d1)); for (d1max = d1[0], i = 1; i < nifos; i ++) if (d1[i] > d1max) d1max = d1[i]; for (i = 0; i < nifos; i ++) d1[i] /= d1max; min_distance /= d1max; max_distance /= d1max; } /* Evaluate posterior term only first. */ P = bayestar_sky_map_toa_adapt_resolution(&pix_perm, &maxpix, npix, gmst, nifos, locations, toas, w_toas, autoresolution_count_pix_toa_snr); if (!P) return NULL; /* Determine the lateral HEALPix resolution. */ nside = npix2nside(*npix); /* Zero pixels that didn't meet the TDOA cut. */ for (i = 0; i < maxpix; i ++) { long ipix = gsl_permutation_get(pix_perm, i); P[ipix] = log(P[ipix]); } for (; i < *npix; i ++) { long ipix = gsl_permutation_get(pix_perm, i); P[ipix] = -INFINITY; } /* Use our own error handler while in parallel section to avoid concurrent * calls to the GSL error handler, which if provided by the user may not * be threadsafe. */ old_handler = gsl_set_error_handler(my_gsl_error); /* Compute posterior factor for amplitude consistency. */ #pragma omp parallel for firstprivate(gsl_errno) lastprivate(gsl_errno) for (i = 0; i < maxpix; i ++) { /* Cancel further computation if a GSL error condition has occurred. * * Note: if one thread sets gsl_errno, not necessarily all thread will * get the updated value. That's OK, because most failure modes will * cause GSL error conditions on all threads. If we cared to have any * failure on any thread terminate all of the other threads as quickly * as possible, then we would want to insert the following pragma here: * * #pragma omp flush(gsl_errno) * * and likewise before any point where we set gsl_errno. */ if (gsl_errno != GSL_SUCCESS) goto skip; { long ipix = gsl_permutation_get(pix_perm, i); double F[nifos][2]; double theta, phi; int itwopsi, iu, iifo; double accum = -INFINITY; /* Prepare workspace for adaptive integrator. */ gsl_integration_workspace *workspace = gsl_integration_workspace_alloc(subdivision_limit); /* If the workspace could not be allocated, then record the GSL * error value for later reporting when we leave the parallel * section. Then, skip to the next loop iteration. */ if (!workspace) { gsl_errno = GSL_ENOMEM; goto skip; } /* Look up polar coordinates of this pixel */ pix2ang_ring(nside, ipix, &theta, &phi); /* Look up antenna factors */ for (iifo = 0; iifo < nifos; iifo ++) { XLALComputeDetAMResponse(&F[iifo][0], &F[iifo][1], responses[iifo], phi, M_PI_2 - theta, 0, gmst); F[iifo][0] *= d1[iifo]; F[iifo][1] *= d1[iifo]; } /* Integrate over 2*psi */ for (itwopsi = 0; itwopsi < ntwopsi; itwopsi++) { const double twopsi = (2 * M_PI / ntwopsi) * itwopsi; const double costwopsi = cos(twopsi); const double sintwopsi = sin(twopsi); /* Integrate over u; since integrand only depends on u^2 we only * have to go from u=0 to u=1. We want to include u=1, so the upper * limit has to be <= */ for (iu = 0; iu <= nu; iu++) { const double u = (double)iu / nu; const double u2 = gsl_pow_2(u); const double u4 = gsl_pow_2(u2); double A = 0, B = 0; double breakpoints[5]; int num_breakpoints = 0; double log_offset = -INFINITY; /* The log-likelihood is quadratic in the estimated and true * values of the SNR, and in 1/r. It is of the form A/r^2 + B/r, * where A depends only on the true values of the SNR and is * strictly negative and B depends on both the true values and * the estimates and is strictly positive. * * The middle breakpoint is at the maximum of the log-likelihood, * occurring at 1/r=-B/2A. The lower and upper breakpoints occur * when the likelihood becomes eta times its maximum value. This * occurs when * * A/r^2 + B/r = log(eta) - B^2/4A. * */ /* Loop over detectors */ for (iifo = 0; iifo < nifos; iifo++) { const double Fp = F[iifo][0]; /* `plus' antenna factor times r */ const double Fx = F[iifo][1]; /* `cross' antenna factor times r */ const double FpFx = Fp * Fx; const double FpFp = gsl_pow_2(Fp); const double FxFx = gsl_pow_2(Fx); const double rhotimesr2 = 0.125 * ((FpFp + FxFx) * (1 + 6*u2 + u4) - gsl_pow_2(1 - u2) * ((FpFp - FxFx) * costwopsi + 2 * FpFx * sintwopsi)); const double rhotimesr = sqrt(rhotimesr2); /* FIXME: due to roundoff, rhotimesr2 can be very small and * negative rather than simply zero. If this happens, don't accumulate the log-likelihood terms for this detector. */ if (rhotimesr2 > 0) { A += rhotimesr2; B += rhotimesr * snrs[iifo]; } } A *= -0.5; { const double middle_breakpoint = -2 * A / B; const double lower_breakpoint = 1 / (1 / middle_breakpoint + sqrt(log(eta) / A)); const double upper_breakpoint = 1 / (1 / middle_breakpoint - sqrt(log(eta) / A)); breakpoints[num_breakpoints++] = min_distance; if(lower_breakpoint > breakpoints[num_breakpoints-1] && lower_breakpoint < max_distance) breakpoints[num_breakpoints++] = lower_breakpoint; if(middle_breakpoint > breakpoints[num_breakpoints-1] && middle_breakpoint < max_distance) breakpoints[num_breakpoints++] = middle_breakpoint; if(upper_breakpoint > breakpoints[num_breakpoints-1] && upper_breakpoint < max_distance) breakpoints[num_breakpoints++] = upper_breakpoint; breakpoints[num_breakpoints++] = max_distance; } { /* * Set log_offset to the maximum of the logarithm of the * radial integrand evaluated at all of the breakpoints. */ int ibreakpoint; for (ibreakpoint = 0; ibreakpoint < num_breakpoints; ibreakpoint++) { const double new_log_offset = log_radial_integrand( breakpoints[ibreakpoint], A, B, prior_distance_power); if (new_log_offset < INFINITY && new_log_offset > log_offset) log_offset = new_log_offset; } } { /* Perform adaptive integration. Stop when a relative * accuracy of 0.05 has been reached. */ inner_integrand_params integrand_params = {A, B, log_offset, prior_distance_power}; const gsl_function func = {radial_integrand, &integrand_params}; double result, abserr; int ret = gsl_integration_qagp(&func, &breakpoints[0], num_breakpoints, DBL_MIN, 0.05, subdivision_limit, workspace, &result, &abserr); /* If the integrator failed, then record the GSL error * value for later reporting when we leave the parallel * section. Then, break out of the loop. */ if (ret != GSL_SUCCESS) { gsl_errno = ret; gsl_integration_workspace_free(workspace); goto skip; } /* Take the logarithm and put the log-normalization back in. */ result = log(result) + integrand_params.log_offset; /* Accumulate result. */ accum = logaddexp(accum, result); } } } /* Discard workspace for adaptive integrator. */ gsl_integration_workspace_free(workspace); /* Accumulate (log) posterior terms for SNR and TDOA. */ P[ipix] += accum; } skip: /* this statement intentionally left blank */; } /* Restore old error handler. */ gsl_set_error_handler(old_handler); /* Free permutation. */ gsl_permutation_free(pix_perm); /* Check if there was an error in any thread evaluating any pixel. If there * was, raise the error and return. */ if (gsl_errno != GSL_SUCCESS) { free(P); GSL_ERROR_NULL(gsl_strerror(gsl_errno), gsl_errno); } /* Exponentiate and normalize posterior. */ pix_perm = get_pixel_ranks(*npix, P); if (!pix_perm) { free(P); return NULL; } exp_normalize(*npix, P, pix_perm); gsl_permutation_free(pix_perm); return P; }
ultranest_results ultranest(LikelihoodFunc, const char * root, const int ndim, const int max_samples, const double logZtol, const int nlive_points, unsigned int nsteps) { unsigned int i = 0; double tolerance = logZtol; int pbar_maxval = nlive_points; char pbar_label[200]; pbar_label[0] = 0; ultranest_draw_state * drawer = ultranest_draw_init(Like, ndim, nsteps, 1.); #ifdef ENABLE_PROGRESSBAR progressbar * pbar = progressbar_new("initialising...", pbar_maxval); pbar->format[1] = '='; #endif ultranest_state * sampler = ultranest_sampler_init(Like, root, ndim, nlive_points, drawer); #ifdef ENABLE_PROGRESSBAR progressbar_update_label(pbar, "sampling..."); progressbar_update(pbar, i); #endif point * current = ultranest_sampler_next(sampler); /* begin integration */ double logVolremaining = 0; double logwidth = log(1 - exp(-1. / sampler->nlive_points)); weighted_point * weights = NULL; ultranest_results res; res.root = root; double wi = logwidth + current->L; double logZ = wi; double H = current->L - logZ; double logZerr; while(1) { logwidth = log(1 - exp(-1. / sampler->nlive_points)) + logVolremaining; logVolremaining -= 1. / sampler->nlive_points; weights = (weighted_point *) realloc(weights, (i+sampler->nlive_points+1) * sizeof(weighted_point)); weights[i].p = current; weights[i].weight = logwidth; i = i + 1; logZerr = sqrt(H / sampler->nlive_points); // double i_final = -sampler->nlive_points * (-sampler->Lmax + logsubexp(fmax(tolerance - logZerr, logZerr / 100.) + logZ, logZ)); // i_final = -sampler.nlive_points * (-sampler.Lmax + log(exp(max(tolerance - logZerr, logZerr / 100.) + logZ) - exp(logZ))) assert(fmax(tolerance - logZerr, logZerr / 100.) > 0); assert(fmax(tolerance - logZerr, logZerr / 100.) + logZ > logZ); int i_final = -(sampler->nlive_points * (-sampler->Lmax + logsubexp(logZ, fmax(tolerance - logZerr, logZerr / 100.)))); pbar_maxval = (int) fmin(fmax(i+1, i_final), i+100000); ultranest_sampler_integrate_remainder(sampler, logwidth, logVolremaining, logZ, NULL); progressbar_settext(pbar_label, i, pbar_maxval, sampler->nlive_points, sampler->ndraws, logZ, sampler->remainderZ, logZerr, sampler->remainderZerr, current, sampler->ndim); #ifdef ENABLE_PROGRESSBAR progressbar_update_label(pbar, pbar_label); pbar->max = pbar_maxval; progressbar_update(pbar, i); #else printf("%s\n", pbar_label); #endif if (i > sampler->nlive_points) { // tolerance double total_error = logZerr + sampler->remainderZerr; if (max_samples > 0 && (unsigned) max_samples < sampler->ndraws) { #ifdef ENABLE_PROGRESSBAR progressbar_finish(pbar); #endif printf("maximum number of samples reached\n"); break; } if (total_error < tolerance) { #ifdef ENABLE_PROGRESSBAR progressbar_finish(pbar); #endif printf("tolerance reached\n"); break; } // we want to make maxContribution as small as possible // but if it becomes 10% of logZerr, that is enough if (sampler->remainderZerr < logZerr / 10.) { #ifdef ENABLE_PROGRESSBAR progressbar_finish(pbar); #endif printf("tolerance will not improve: remainder error (%.3f) is much smaller than systematic errors (%.3f)\n", sampler->remainderZerr, logZerr); break; } } current = ultranest_sampler_next(sampler); wi = logwidth + current->L; double logZnew = logaddexp(logZ, wi); H = exp(wi - logZnew) * current->L + exp(logZ - logZnew) * (H + logZ) - logZnew; logZ = logZnew; } // not needed for integral, but for posterior samples, otherwise there // is a hole in the most likely parameter ranges. i += ultranest_sampler_integrate_remainder(sampler, logwidth, logVolremaining, logZ, weights + i); logZerr += sampler->remainderZerr; logZ = logaddexp(logZ, sampler->remainderZ); res.logZ = logZ; res.logZerr = logZerr; res.ndraws = sampler->ndraws; res.niter = i; res.H = H; res.weighted_points = weights; printf("ULTRANEST result: lnZ = %.2f +- %.2f\n", res.logZ, res.logZerr); write_results(root, res, ndim); return res; }