10 #include <configure.hpp>
31 for (i = 0; i < n; ++i)
32 for (
j = i;
j < n; ++
j) {
33 for (sum =
a[i][
j], k = i - 1; k >= 0; --k) {
34 sum -=
a[i][k] *
a[
j][k];
54 #define MAXLAG TAUMAX *WINMULT
60 int _acor(
double *mean,
double *sigma,
double *tau,
double *
X,
int L) {
62 for (
int i = 0; i < L; i++) *mean +=
X[i];
64 for (
int i = 0; i < L; i++)
X[i] -= *mean;
73 for (
int s = 0; s <=
MAXLAG; s++)
78 for (
int i = 0; i < iMax; i++)
79 for (
int s = 0; s <=
MAXLAG; s++)
80 C[s] +=
X[i] *
X[i + s];
81 for (
int s = 0; s <=
MAXLAG; s++)
86 for (
int s = 1; s <=
MAXLAG; s++)
105 for (
int i = 0; i < Lh; i++) {
106 X[i] =
X[j1] +
X[j2];
110 _acor(&newMean, sigma, tau,
X, Lh);
111 D = .25 * (*sigma) * (*sigma) *
115 *sigma = sqrt(D / L);
137 memset(recs->
par[0][0], 0, nstep * nwalker * ndim *
sizeof(
double));
138 memset(recs->
val[0][0], 0, nstep * nwalker * nvalue *
sizeof(
double));
139 memset(recs->
lnp[0], 0, nstep * nwalker *
sizeof(
double));
140 memset(recs->
newstate[0], 0, nstep * nwalker *
sizeof(
int));
142 recs->
opt_par =
new double[ndim];
143 recs->
opt_val =
new double[nvalue];
162 double *x =
new double[recs->
cur];
164 for (
size_t p = 0;
p < recs->
ndim; ++
p) {
165 for (
size_t t = 0; t < recs->
cur; ++t) {
167 for (
size_t k = 0; k < recs->
nwalker; ++k) x[t] += recs->
par[t][k][
p];
171 int err =
_acor(mean +
p, sigma +
p, tau +
p, x, recs->
cur);
173 if (err != 0) tau[
p] = -1.;
184 double ***par, ***val, **lnp;
188 int rank = 0, size = 1;
190 int ndim = recs->
ndim;
191 int nvalue = recs->
nvalue;
192 int cur = include_last ? recs->
cur : recs->
cur - 1;
194 int accept = recs->
accept;
195 int reset = recs->
reset;
196 double opt_lnp = recs->
opt_lnp;
199 if (cur <= 0)
return;
202 MPI_Comm_rank(opts->mpi_comm, &rank);
203 MPI_Comm_size(opts->mpi_comm, &size);
205 NewCArray(par, cur, size * nwalker, ndim);
206 NewCArray(val, cur, size * nwalker, nvalue);
208 NewCArray(newstate, cur, size * nwalker);
211 NewCArray(buf, size, cur * nwalker, ndim);
212 MPI_Gather(**recs->
par, cur * nwalker * ndim, MPI_DOUBLE, **buf,
213 cur * nwalker * ndim, MPI_DOUBLE, 0, opts->mpi_comm);
215 for (
int t = 0; t < cur; ++t)
216 for (
int r = 0;
r < size; ++
r)
217 for (
int k = 0; k < nwalker; ++k)
218 for (
int d = 0; d < ndim; ++d)
219 par[t][
r * nwalker + k][d] = buf[
r][t * nwalker + k][d];
224 NewCArray(buf, size, cur * nwalker, nvalue);
225 MPI_Gather(**recs->
val, cur * nwalker * nvalue, MPI_DOUBLE, **buf,
226 cur * nwalker * nvalue, MPI_DOUBLE, 0, opts->mpi_comm);
228 for (
int t = 0; t < cur; ++t)
229 for (
int r = 0;
r < size; ++
r)
230 for (
int k = 0; k < nwalker; ++k)
231 for (
int d = 0; d < nvalue; ++d)
232 val[t][
r * nwalker + k][d] = buf[
r][t * nwalker + k][d];
238 MPI_Gather(*recs->
lnp, cur * nwalker, MPI_DOUBLE, **buf, cur * nwalker,
239 MPI_DOUBLE, 0, opts->mpi_comm);
241 for (
int t = 0; t < cur; ++t)
242 for (
int r = 0;
r < size; ++
r)
243 for (
int k = 0; k < nwalker; ++k)
244 lnp[t][
r * nwalker + k] = buf[
r][t][k];
249 MPI_Reduce(&recs->
opt_lnp, &opt_lnp, 1, MPI_DOUBLE, MPI_MAX, 0,
253 MPI_Reduce(&recs->
accept, &accept, 1, MPI_INT, MPI_SUM, 0, opts->mpi_comm);
256 MPI_Reduce(&recs->
reset, &reset, 1, MPI_INT, MPI_SUM, 0, opts->mpi_comm);
260 MPI_Gather(*recs->
newstate, cur * nwalker, MPI_INT, **ibuf, cur * nwalker,
261 MPI_INT, 0, opts->mpi_comm);
263 for (
int t = 0; t < cur; ++t)
264 for (
int r = 0;
r < size; ++
r)
265 for (
int k = 0; k < nwalker; ++k)
266 newstate[t][
r * nwalker + k] = ibuf[
r][t][k];
277 long naxes[3] = {ndim, size * nwalker, cur};
279 long nelements = naxes[0] * naxes[1] * naxes[2];
281 fits_create_file(&fp, fname, &status);
282 if (status) fits_report_error(stderr, status);
285 fits_create_img(fp, DOUBLE_IMG, naxis, naxes, &status);
286 if (status) fits_report_error(stderr, status);
290 fits_write_img(fp, TDOUBLE, fpixel, nelements, **par, &status);
292 fits_write_img(fp, TDOUBLE, fpixel, nelements, **recs->
par, &status);
294 if (status) fits_report_error(stderr, status);
297 char key[80] =
"C.Li";
298 fits_write_key(fp, TSTRING,
"CREATOR", key,
"file created by Cheng Li",
301 snprintf(key,
sizeof(key),
"%s",
"par");
302 fits_write_key(fp, TSTRING,
"VAR", key,
"retrieved parameters", &status);
304 snprintf(key,
sizeof(key),
"%s",
"MCMC");
305 fits_write_key(fp, TSTRING,
"METHOD", key,
"retrieval method", &status);
307 fits_write_key(fp, TDOUBLE,
"A", &opts->
a,
"stretch move parameter",
309 fits_write_key(fp, TINT,
"P", &opts->
p,
"walk move parameter", &status);
311 fits_write_key(fp, TDOUBLE,
"LOGP", &opt_lnp,
"optimal log probability",
313 fits_write_key(fp, TINT,
"RESET", &reset,
"number of resetted states",
315 fits_write_key(fp, TINT,
"ACCEPT", &accept,
"number of accepted states",
320 nelements = naxes[0] * naxes[1] * naxes[2];
321 fits_create_img(fp, DOUBLE_IMG, naxis, naxes, &status);
322 if (status) fits_report_error(stderr, status);
326 fits_write_img(fp, TDOUBLE, fpixel, nelements, **val, &status);
328 fits_write_img(fp, TDOUBLE, fpixel, nelements, **recs->
val, &status);
330 if (status) fits_report_error(stderr, status);
332 snprintf(key,
sizeof(key),
"%s",
"val");
333 fits_write_key(fp, TSTRING,
"VAR", key,
"values of forward model", &status);
337 nelements = naxes[1] * naxes[2];
338 fits_create_img(fp, DOUBLE_IMG, naxis, naxes + 1, &status);
339 if (status) fits_report_error(stderr, status);
341 snprintf(key,
sizeof(key),
"%s",
"lnp");
342 fits_write_key(fp, TSTRING,
"VAR", key,
"log probability", &status);
346 fits_write_img(fp, TDOUBLE, fpixel, nelements, *lnp, &status);
348 fits_write_img(fp, TDOUBLE, fpixel, nelements, *recs->
lnp, &status);
350 if (status) fits_report_error(stderr, status);
353 fits_create_img(fp, SHORT_IMG, naxis, naxes + 1, &status);
354 if (status) fits_report_error(stderr, status);
356 snprintf(key,
sizeof(key),
"%s",
"inew");
357 fits_write_key(fp, TSTRING,
"VAR", key,
"new state indicator", &status);
361 fits_write_img(fp, TINT, fpixel, nelements, *newstate, &status);
363 fits_write_img(fp, TINT, fpixel, nelements, *recs->
newstate, &status);
365 if (status) fits_report_error(stderr, status);
367 fits_close_file(fp, &status);
381 int status = 0, hdutype;
382 int nstep, nwalker, ndim, nvalue;
383 long dims[3] = {1, 1, 1};
384 long fpixel[3] = {1, 1, 1};
390 fits_open_file(&fp, fname, READONLY, &status);
392 fits_report_error(stderr, status);
397 fits_movabs_hdu(fp, 1, &hdutype, &status);
400 fits_get_img_size(fp, 3, dims, &status);
406 fits_movabs_hdu(fp, 2, &hdutype, &status);
407 fits_get_img_size(fp, 3, dims, &status);
412 mcmc_alloc(recs, nstep, nwalker, ndim, nvalue);
414 assert(recs->
nstep >= nstep);
415 assert(recs->
nwalker == nwalker);
416 assert(recs->
ndim == ndim);
417 assert(recs->
nvalue == nvalue);
421 fits_movabs_hdu(fp, 1, &hdutype, &status);
422 fits_read_pix(fp, TDOUBLE, fpixel, nstep * nwalker * ndim, NULL, **recs->
par,
426 fits_read_key(fp, TDOUBLE,
"LOGP", &recs->
opt_lnp, NULL, &status);
427 fits_read_key(fp, TDOUBLE,
"A", &opts->
a, NULL, &status);
428 fits_read_key(fp, TINT,
"P", &opts->
p, NULL, &status);
429 fits_read_key(fp, TINT,
"RESET", &recs->
reset, NULL, &status);
430 fits_read_key(fp, TINT,
"ACCEPT", &recs->
accept, NULL, &status);
433 fits_movabs_hdu(fp, 2, &hdutype, &status);
434 fits_read_pix(fp, TDOUBLE, fpixel, nstep * nwalker * nvalue, NULL,
435 **recs->
val, NULL, &status);
438 fits_movabs_hdu(fp, 3, &hdutype, &status);
439 fits_read_pix(fp, TDOUBLE, fpixel, nstep * nwalker, NULL, *recs->
lnp, NULL,
443 fits_movabs_hdu(fp, 4, &hdutype, &status);
445 fits_read_pix(fp, TINT, fpixel, nstep * nwalker, NULL, *recs->
newstate, NULL,
449 fits_report_error(stderr, status);
455 fits_close_file(fp, &status);
470 memcpy(*dst->
par[cur], **src->
par, size_par *
sizeof(
double));
471 memcpy(*dst->
val[cur], **src->
val, size_val *
sizeof(
double));
472 memcpy(dst->
lnp[cur], *src->
lnp, size_lnp *
sizeof(
double));
487 int rank = 0, size = 1;
488 double **par, *lnp, **opt_par, **opt_val;
490 double *mean, *sigma, *tau, **cov;
499 int ndim = recs->
ndim;
500 int nvalue = recs->
nvalue;
504 mean =
new double[ndim];
505 sigma =
new double[ndim];
506 tau =
new double[ndim];
511 for (
int d = 0; d < ndim; ++d) {
513 for (
int t = 0; t < cur; ++t)
514 for (
int k = 0; k < nwalker; ++k)
515 sigma[d] +=
sqr(recs->
par[t][k][d] - mean[d]);
519 for (
int i = 0; i < ndim; ++i)
520 for (
int j = 0;
j < ndim; ++
j) {
522 for (
int t = 0; t < cur; ++t)
523 for (
int k = 0; k < nwalker; ++k)
525 (recs->
par[t][k][i] - mean[i]) * (recs->
par[t][k][
j] - mean[
j]);
529 MPI_Comm_rank(opts->mpi_comm, &rank);
530 MPI_Comm_size(opts->mpi_comm, &size);
532 lnp =
new double[nwalker * size];
538 MPI_Gather(*recs->
par[cur - 1], nwalker * ndim, MPI_DOUBLE, *par,
539 nwalker * ndim, MPI_DOUBLE, 0, opts->mpi_comm);
542 MPI_Gather(recs->
lnp[cur - 1], nwalker, MPI_DOUBLE, lnp, nwalker, MPI_DOUBLE,
546 MPI_Gather(recs->
opt_par, ndim, MPI_DOUBLE, *opt_par, ndim, MPI_DOUBLE, 0,
550 MPI_Gather(recs->
opt_val, nvalue, MPI_DOUBLE, *opt_val, nvalue, MPI_DOUBLE, 0,
557 MPI_Reduce(MPI_IN_PLACE, &opt_lnp, 1, MPI_DOUBLE_INT, MPI_MAXLOC, 0,
560 MPI_Reduce(&opt_lnp, &opt_lnp, 1, MPI_DOUBLE_INT, MPI_MAXLOC, 0,
564 MPI_Reduce(&recs->
accept, &accept, 1, MPI_INT, MPI_SUM, 0, opts->mpi_comm);
567 MPI_Allreduce(MPI_IN_PLACE, mean, ndim, MPI_DOUBLE, MPI_SUM, opts->mpi_comm);
568 for (
int d = 0; d < ndim; ++d) mean[d] /= size;
572 MPI_Reduce(MPI_IN_PLACE, sigma, ndim, MPI_DOUBLE, MPI_SUM, 0,
575 MPI_Reduce(sigma, sigma, ndim, MPI_DOUBLE, MPI_SUM, 0, opts->mpi_comm);
579 MPI_Reduce(MPI_IN_PLACE, *cov, ndim * ndim, MPI_DOUBLE, MPI_SUM, 0,
582 MPI_Reduce(*cov, *cov, ndim * ndim, MPI_DOUBLE, MPI_SUM, 0, opts->mpi_comm);
586 MPI_Reduce(MPI_IN_PLACE, tau, ndim, MPI_DOUBLE, MPI_SUM, 0, opts->mpi_comm);
588 MPI_Reduce(tau, tau, ndim, MPI_DOUBLE, MPI_SUM, 0, opts->mpi_comm);
589 for (
int d = 0; d < ndim; ++d) tau[d] /= size;
591 par = recs->
par[cur - 1];
592 lnp = recs->
lnp[cur - 1];
593 opt_par =
new double *[1];
595 opt_val =
new double *[1];
603 for (
int d = 0; d < ndim; ++d)
604 sigma[d] = sqrt(sigma[d] / (nwalker * size * cur));
607 for (
int i = 0; i < ndim; ++i)
608 for (
int j = 0;
j < ndim; ++
j) cov[i][
j] /= size * nwalker * cur;
612 FILE *fout = fopen(opts->
logfile, mode);
614 fprintf(fout,
"#### MCMC Iteration: No. %d ####\n", recs->
reset + cur);
616 fprintf(fout,
"1. Current positions:\n");
617 fprintf(fout,
"%3s",
" ");
618 for (
int d = 0; d < ndim; ++d) fprintf(fout,
"%9s%-2d",
"D", d + 1);
620 for (
int k = 0; k < nwalker * size; k++) {
621 fprintf(fout,
"%3d",
static_cast<int>(k) + 1);
622 for (
int d = 0; d < ndim; ++d) fprintf(fout,
"%11.4g", par[k][d]);
623 fprintf(fout,
" |%9.4f\n", lnp[k]);
628 fprintf(fout,
"2. Optimal parameters:\n");
629 fprintf(fout,
"%3s",
" ");
630 for (
int d = 0; d < ndim; ++d)
631 fprintf(fout,
"%11.4g", opt_par[opt_lnp.rank][d]);
635 fprintf(fout,
"4. Mean value:\n");
636 fprintf(fout,
"%3s",
" ");
637 for (
int d = 0; d < ndim; ++d) fprintf(fout,
"%11.4g", mean[d]);
641 fprintf(fout,
"4. Standard deviation:\n");
642 fprintf(fout,
"%3s",
" ");
643 for (
int d = 0; d < ndim; ++d) fprintf(fout,
"%11.4g", sigma[d]);
647 fprintf(fout,
"5. Correlation coefficient:\n");
648 for (
int i = 0; i < ndim; ++i) {
649 fprintf(fout,
"%1s%-2d",
"D", i + 1);
650 for (
int j = 0;
j < ndim; ++
j)
651 fprintf(fout,
"%11.4g", cov[i][
j] / (sigma[i] * sigma[
j]));
656 fprintf(fout,
"6. Autocorrelation time:\n");
657 fprintf(fout,
"%3s",
" ");
658 for (
int d = 0; d < ndim; ++d) fprintf(fout,
"%11.4g", tau[d]);
662 fprintf(fout,
"7. Optimal model results:\n");
663 for (
int d = 0; d < nvalue; ++d) {
664 fprintf(fout,
"%11.4f", opt_val[opt_lnp.rank][d]);
665 if ((d + 1) % 6 == 0) fprintf(fout,
"\n");
667 if (nvalue % 6 != 0) fprintf(fout,
"\n");
670 fprintf(fout,
"8. Optimal log probability:\n");
671 fprintf(fout,
"%11.4g\n", opt_lnp.value);
674 fprintf(fout,
"9. Acceptance fraction:\n");
675 fprintf(fout,
"%11.4g",
676 1. * accept / ((recs->
reset + cur) * nwalker * size));
677 fprintf(fout,
"\n##############################\n");
701 int ndim = recs->
ndim;
705 for (
int k = 0; k < nwalker; ++k) {
706 recs->
lnp[0][k] = lnprob(par[k], recs->
val[0][k], ndim, nval, obj);
709 while (std::isnan(recs->
lnp[0][k]) &&
712 recs->
lnp[0][k] = lnprob(par[k], recs->
val[0][k], ndim, nval, obj);
716 std::cerr <<
"Starting point iteration > 10 times" << std::endl;
721 for (
int d = 0; d < ndim; ++d) recs->
par[0][k][d] = par[k][d];
725 for (
int d = 0; d < ndim; ++d) recs->
opt_par[d] = recs->
par[0][k][d];
726 for (
int d = 0; d < nval; ++d) recs->
opt_val[d] = recs->
val[0][k][d];
741 int ndim = recs->
ndim;
745 double *par =
new double[ndim];
747 unsigned int seed =
time(NULL);
748 for (
int k = 0; k < nwalker; ++k) {
753 recs->
lnp[cur][k] = lnprob(par, recs->
val[cur][k], ndim, nval, obj);
755 double lnp0 = recs->
lnp[cur - 1][k], lnp1 = recs->
lnp[cur][k],
756 pdiff = (ndim - 1.) * log(zz) + lnp1 - lnp0;
758 if (pdiff > log(1. * rand_r(&seed) / RAND_MAX)) {
759 for (
int d = 0; d < ndim; ++d) recs->
par[cur][k][d] = par[d];
763 for (
int d = 0; d < ndim; ++d) recs->
opt_par[d] = recs->
par[cur][k][d];
764 for (
int d = 0; d < nval; ++d) recs->
opt_val[d] = recs->
val[cur][k][d];
770 for (
int d = 0; d < ndim; ++d)
771 recs->
par[cur][k][d] = recs->
par[cur - 1][k][d];
772 for (
int d = 0; d < nval; ++d)
773 recs->
val[cur][k][d] = recs->
val[cur - 1][k][d];
774 recs->
lnp[cur][k] = recs->
lnp[cur - 1][k];
786 int irank = 0, size = 1;
790 MPI_Comm_rank(opts->mpi_comm, &irank);
791 MPI_Comm_size(opts->mpi_comm, &size);
797 MPI_Allgather(*oldp, nwalker * ndim, MPI_DOUBLE, **par, nwalker * ndim,
798 MPI_DOUBLE, opts->mpi_comm);
800 for (
int k = 0; k < nwalker; ++k)
801 for (
int d = 0; d < ndim; ++d) par[0][k][d] = oldp[k][d];
805 unsigned int seed =
time(NULL);
806 double r = 1. * rand_r(&seed) / RAND_MAX;
808 double zz = ((opts->
a - 1.) *
r + 1.) * ((opts->
a - 1.) *
r + 1) / opts->
a;
811 int jrank = rand_r(&seed) % size;
812 if (jrank == irank) {
813 jwalker = rand_r(&seed) % (nwalker - 1);
814 if (jwalker >= iwalker) jwalker++;
816 jwalker = rand_r(&seed) % nwalker;
819 for (
int d = 0; d < ndim; ++d)
820 newp[d] = (1. - zz) * par[jrank][jwalker][d] + zz * par[irank][iwalker][d];
829 int *sub =
new int[opts->
p];
831 double *mean =
new double[np], *diag =
new double[np];
837 assert(opts->
p <
static_cast<int>(nwalker));
838 assert(opts->
p >
static_cast<int>(np));
840 unsigned int seed =
time(NULL);
842 for (
int i = 0; i < opts->
p; ++i) {
844 int s = rand_r(&seed) % (nwalker - 1);
845 if (s >=
static_cast<int>(k)) s++;
847 for (
int j = 0;
j < i; ++
j)
848 if (sub[
j] == s) redraw =
true;
849 if (!redraw) sub[i] = s;
854 for (
size_t p = 0;
p < np; ++
p) {
856 for (
int q = 0; q < opts->
p; ++q) mean[
p] += oldp[sub[q]][
p];
861 for (
size_t i = 0; i < np; ++i) {
862 for (
size_t j = 0;
j < np; ++
j) {
864 for (
int q = 0; q < opts->
p; ++q)
865 cov[i][
j] += (oldp[sub[q]][i] - mean[i]) * (oldp[sub[q]][
j] - mean[
j]);
866 cov[i][
j] /= opts->
p;
879 for (
size_t i = 0; i < np; ++i) {
880 double u = 1. * rand_r(&seed) / RAND_MAX;
881 double v = 1. * rand_r(&seed) / RAND_MAX;
883 mean[i] = sqrt(-2. * log(u)) * cos(2. * M_PI * v);
887 for (
size_t i = 0; i < np; ++i) {
888 newp[i] = oldp[k][i];
889 for (
size_t j = 0;
j < i; ++
j) newp[i] += cov[i][
j] * mean[
j];
890 newp[i] += diag[i] * mean[i];
void mcmc_load_fits(char const *fname, mcmc_opts *opts, mcmc_recs *recs, int alloc)
void mcmc_statistics(double *mean, double *sigma, double *tau, mcmc_recs *recs)
void mcmc_append_recs(mcmc_recs *dst, mcmc_recs *src)
void _choldc(double **a, int n, double *p)
void mcmc_advance(ObjectiveFunction_t lnprob, mcmc_opts *opts, mcmc_recs *recs, void *obj)
void mcmc_report(mcmc_opts *opts, mcmc_recs *recs, char const *mode)
void mcmc_init(ObjectiveFunction_t lnprob, double **par, mcmc_opts *opts, mcmc_recs *recs, void *obj)
void mcmc_free(mcmc_recs *recs)
int _acor(double *mean, double *sigma, double *tau, double *X, int L)
void mcmc_alloc(mcmc_recs *recs, int nstep, int nwalker, int ndim, int nvalue)
void mcmc_save_fits(char const *fname, mcmc_opts *opts, mcmc_recs *recs, int include_last)
void mcmc_walk_move(double *newp, double **oldp, int k, int nwalker, int np, mcmc_opts *opts)
double mcmc_stretch_move(double *newp, double **oldp, int iwalker, int nwalker, int ndim, mcmc_opts *opts)
This file contains data structure and subroutines implementing Markov Chain Monte Carlo sampler.
double(* ObjectiveFunction_t)(double *, double *, int, int, void *)
void NewCArray(T **&a, int n1, int n2)