diff --git a/CMakeLists.txt b/CMakeLists.txt index b4f0fe6..a61cec8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Custom minimal -*- CMake -*- file for wham cmake_minimum_required(VERSION 3.16) -project(wham VERSION 2.0.11 +project(wham VERSION 2.1.0 DESCRIPTION "WHAM: a fast, memory efficient implementation of the Weighted Histogram Analysis Method" LANGUAGES C HOMEPAGE_URL http://membrane.urmc.rochester.edu/content/wham/) diff --git a/doc/doc.tex b/doc/doc.tex index cf36616..84ee891 100644 --- a/doc/doc.tex +++ b/doc/doc.tex @@ -53,7 +53,7 @@ Suggestions and patches are welcome. \subsection{New in release 2.1.0} -Two changes, both contributed by Alex Kohlmeyer. First, we switched from old +Two changes, both contributed by Axel Kohlmeyer. First, we switched from old make to CMake for the build. Second, we changed how energy units are set; where it used to be a compile-time option, now it is set on the command line. diff --git a/wham-2d/histogram.c b/wham-2d/histogram.c index 1bd1329..b5d1c01 100644 --- a/wham-2d/histogram.c +++ b/wham-2d/histogram.c @@ -78,14 +78,14 @@ return hp; } /* Get a value from a histogram structure - * Given i and j, the indices into the global histogram, return + * Given i and j, the indices into the global histogram, return * the correct histogram value. Since we only store range of histogram - * indices containing the nonzero values, we have to check the index value + * indices containing the nonzero values, we have to check the index value * against the range in the structure. */ double get_histval(struct histogram *hist, int i, int j) { -if ( (i < hist->first_x) || (i > hist->last_x) +if ( (i < hist->first_x) || (i > hist->last_x) ||(j < hist->first_y) || (j > hist->last_y)) { return 0.0; @@ -239,7 +239,7 @@ return error; // Calculate the free energy, setting the minimum value to 0 -void calc_free(double **free, double **prob, double kT, +void calc_free(double **free, double **prob, double kT, int use_mask, int **mask) { int i,j; @@ -257,7 +257,14 @@ for (i=0; i 0.0) + { + free[i][j] = -kT * log(prob[i][j]); + } + else + { + free[i][j] = 0.0; + } if (free[i][j] < min) { min = free[i][j]; @@ -321,8 +328,6 @@ return 0.5*(springx*(dx*dx) + springy*(dy*dy)); void calc_coor(int i, int j, double *coor) { -coor[0] = HIST_MINx + BIN_WIDTHx*((double)i+0.5); -coor[1] = HIST_MINy + BIN_WIDTHy*((double)j+0.5); +coor[0] = HIST_MINx + BIN_WIDTHx*((double)i+0.5); +coor[1] = HIST_MINy + BIN_WIDTHy*((double)j+0.5); } - - diff --git a/wham-2d/wham-2d.c b/wham-2d/wham-2d.c index 76389ac..05fe7cf 100644 --- a/wham-2d/wham-2d.c +++ b/wham-2d/wham-2d.c @@ -417,8 +417,8 @@ while ( ! iConverged || first) for (j=0; j< NUM_BINSy; j++) { calc_coor(i,j,coor); - printf("%f\t%f\t%f\t%f\n", coor[0], coor[1], free_ene[i][j], - prob[i][j]); + if (prob[i][j] != 0.0) + printf("%f\t%f\t%f\t%f\n", coor[0], coor[1], free_ene[i][j], prob[i][j]); } } @@ -501,8 +501,9 @@ if (!FREEFILE) for (j=0; j< NUM_BINSy; j++) { calc_coor(i,j,coor); - printf("%f\t%f\t%f\t%f\n", coor[0], coor[1], - free_ene[i][j], final_prob[i][j]); + if (prob[i][j] != 0.0) + printf("%f\t%f\t%f\t%f\n", coor[0], coor[1], + free_ene[i][j], final_prob[i][j]); } } exit(errno); @@ -518,25 +519,28 @@ else for (j=-numpad; j<0; j++) { calc_coor(i,j,coor); - fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1], - free_ene[NUM_BINSx+i][NUM_BINSy+j], - final_prob[NUM_BINSx+i][NUM_BINSy+j]); + if (prob[NUM_BINSx+i][NUM_BINSy+j] != 0.0) + fprintf(FREEFILE,"%f\t%f\t%f\t%f\n", coor[0], coor[1], + free_ene[NUM_BINSx+i][NUM_BINSy+j], + final_prob[NUM_BINSx+i][NUM_BINSy+j]); } // center values in y for (j=0; j 0.0) + { + free[i] = -kT * log(prob[i]); + } + else + { + free[i] = 0.0; + } + + if (free[i] < min) { min = free[i]; bin_min = i; @@ -252,5 +260,5 @@ return 0.5*dx*dx*spring; double calc_coor(int i) { -return HIST_MIN + BIN_WIDTH*((double)i+0.5); +return HIST_MIN + BIN_WIDTH*((double)i+0.5); } diff --git a/wham/wham.c b/wham/wham.c index 19cf695..7bdbce1 100644 --- a/wham/wham.c +++ b/wham/wham.c @@ -1,4 +1,4 @@ -/* +/* * WHAM -- Weighted Histogram Analysis Method * * Reference 1: Computer Physics Communications, 91(1995) 275-282, Benoit Roux @@ -39,10 +39,9 @@ double kT; // temperature int i,j; int len; int first; -int bin_min; int have_energy; char *freefile; -FILE *METAFILE, *FREEFILE; +FILE *METAFILE, *FREEFILE; struct hist_group *hist_group; struct histogram *hp; double coor; @@ -179,7 +178,7 @@ if (argc != 9 && argc !=11) printf( COMMAND_LINE ); exit(-1); } - + HIST_MIN = atof(argv[1]); HIST_MAX = atof(argv[2]); NUM_BINS = atoi(argv[3]); @@ -269,13 +268,13 @@ if (!ave_pdf2) printf("couldn't allocate space for ave_pdf2: %s\n", strerror(errno)); exit(errno); } - + free_ene = (double *) malloc(sizeof(double) * NUM_BINS); if (!free_ene) { printf("couldn't allocate space for free_ene: %s\n", strerror(errno)); exit(errno); - } + } i = get_numwindows(METAFILE); printf("#Number of windows = %d\n", i); @@ -304,7 +303,7 @@ assert(i == hist_group->num_windows); // Figure out if we have trajectories at different temperatures. // Missing temperatures are set to -1 in read_metadata, and // since we require that either all trajectories specify a temperature -// or all trajectories are assumed to be at the wham temperature, we only +// or all trajectories are assumed to be at the wham temperature, we only // have to check one of them if (hist_group->kT[0] > 0) { @@ -313,7 +312,7 @@ if (hist_group->kT[0] > 0) else { have_energy = 0; - for (i=0; i< hist_group->num_windows; i++) + for (i=0; i< hist_group->num_windows; i++) { hist_group->kT[i] = kT; } @@ -325,7 +324,7 @@ if (!final_f) { printf("couldn't allocate space for final_f: %s\n", strerror(errno)); exit(errno); - } + } free(HISTOGRAM); @@ -361,7 +360,8 @@ while (! is_converged(hist_group) || first ) for (i=0; i< NUM_BINS; i++) { coor = calc_coor(i); - printf("%f\t%f\t%f\n", coor, free_ene[i], prob[i]); + if (prob[i] != 0.0) + printf("%f\t%f\t%f\n", coor, free_ene[i], prob[i]); } printf("\n"); @@ -375,7 +375,7 @@ while (! is_converged(hist_group) || first ) } } // Cheesy bailout if we're going on too long - if (iteration >= max_iteration) + if (iteration >= max_iteration) { printf("Too many iterations: %d\n", iteration); break; @@ -408,7 +408,7 @@ for (i=0; i < NUM_BINS; i++) } // Compute the free energy from the normalized probability -bin_min = calc_free(free_ene, prob,kT); + calc_free(free_ene, prob,kT); // Do the requested number of bootstrap monte carlo error analysis runs. if (num_mc_runs <= 0) @@ -439,11 +439,11 @@ for (i=0; i< num_mc_runs; i++) //printf("Faking %d: %d %d\n", i,j,hp->num_points); num_used = hp->last - hp->first + 1; mk_new_hist(hp->cum, hp->data, num_used, hp->num_mc_samples, &idum); - + hist_group->F_old[j] = 0.0; hist_group->F[j] = 0.0; } - + // perform WHAM iterations on the fake data sets iteration = 0; first = 1; @@ -459,7 +459,7 @@ for (i=0; i< num_mc_runs; i++) printf("Too many iterations: %d\n", iteration); break; } - } + } printf("#MC trial %d: %d iterations\n", i, iteration); printf("#PMF values\n"); // accumulate the average and stdev of the resulting probabilities @@ -475,18 +475,19 @@ for (i=0; i< num_mc_runs; i++) for (j=0; j < NUM_BINS; j++) { pdf = -kT*log(prob[j]); - + ave_p[j] += prob[j]; ave_pdf[j] += pdf; ave_p2[j] += prob[j] * prob[j]; ave_pdf2[j] += pdf*pdf; } - for (j=0; jnum_windows;j++) + for (j=0; jnum_windows;j++) { ave_F[j] += hist_group->F[j] - hist_group->F[0]; - ave_F2[j] += hist_group->F[j]*hist_group->F[j] ; + ave_F2[j] += hist_group->F[j]*hist_group->F[j] ; } - } + } + if (num_mc_runs == 0) num_mc_runs = 1; for (i=0; i < NUM_BINS; i++) { ave_p[i] /= (double)num_mc_runs; @@ -513,12 +514,12 @@ if (!FREEFILE) for (i=0; i< NUM_BINS; i++) { coor = calc_coor(i); - printf("%f\t%f\t%f\t%f\t%f\n", coor, free_ene[i], ave_pdf2[i], - prob[i], ave_p2[i]); + if (prob[i] != 0.0) + printf("%f\t%f\t%f\t%f\t%f\n", coor, free_ene[i], ave_pdf2[i], prob[i], ave_p2[i]); } for (i=0; inum_windows; i++) { - fprintf(FREEFILE,"%d\t%f\t%f\n", i, final_f[i],ave_F2[i]); + printf("%d\t%f\t%f\n", i, final_f[i],ave_F2[i]); } exit(errno); @@ -526,38 +527,37 @@ if (!FREEFILE) else { // write out header - fprintf(FREEFILE, "#Coor\t\tFree\t+/-\t\tProb\t\t+/-\n"); + fprintf(FREEFILE, "#Coor\t\tFree\t\t+/-\t\tProb\t\t+/-\n"); // write out the leading padded values for (i=-numpad; i<0; i++) { coor = calc_coor(i); - fprintf(FREEFILE,"%f\t%f\t%f\t%f\t%f\n", coor, free_ene[NUM_BINS+i], - ave_pdf2[NUM_BINS+i], - final_prob[NUM_BINS+i], - ave_p2[NUM_BINS+i]); + if (prob[NUM_BINS+1] != 0.0) + fprintf(FREEFILE,"%f\t%f\t%f\t%f\t%f\n", coor, free_ene[NUM_BINS+i], + ave_pdf2[NUM_BINS+i], final_prob[NUM_BINS+i], ave_p2[NUM_BINS+i]); } // write out the center values for (i=0; inum_windows; i++) { - fprintf(FREEFILE,"#%d\t%f\t%f\n", i, final_f[i],ave_F2[i]); + fprintf(FREEFILE,"#%d\t\t%f\t%f\n", i, final_f[i],ave_F2[i]); } } @@ -571,7 +571,7 @@ exit(0); /* * Perform a single WHAM iteration */ -void wham_iteration(struct hist_group* hist_group, double *prob, +void wham_iteration(struct hist_group* hist_group, double *prob, int have_energy) { int i,j; @@ -591,9 +591,9 @@ for (i=0; ihists[j]),i); bias = calc_bias(hist_group,j,coor); bf = exp((hist_group->F_old[j] - bias) / hist_group->kT[j]); - /* If we have energies, then the histograms contain boltzmann - * factors. If not, they contain integer counts. Accordingly, - * we either use a partition function to normalize, or simply the + /* If we have energies, then the histograms contain boltzmann + * factors. If not, they contain integer counts. Accordingly, + * we either use a partition function to normalize, or simply the * number of points. */ if (have_energy)