Documents/NamdSample/namd210/lib/replica/FEP_wca/wham/wham-fep.cpp (331 lines of code) (raw):
// Code written by Lei Huang for wham post-process of FEP data in NAMD
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define KBOLTZ (1.987191E-03)
#define NCYCLE (100000)
//#define TOL (1.0E-7)
#define TOL (1.0E-6)
#define max_data (1000000)
#define max_wind (20)
#define CHECK_POINTER(p) {if((p)==NULL) {printf("Invalid pointer.\nQuit\n"); exit(1);}}
int *NPoints;
double **epprtd;
double *lambda;
double *F;
double *F2;
int nb_wind;
double kbt;
char szData[256];
char szFile_FE[256];
// max_data - max number of data points
// max_wind - max number of windows
void wham_FEP(void);
void wham(void);
void wham_E_Histogram(void);
double** Allocate_Mem_2D_Array(int Ny, int Nx);
void Deallocate_Mem_2D_Array(double **p, int Ny, int Nx);
int** Allocate_Mem_2D_Array_Int(int Ny, int Nx);
void Deallocate_Mem_2D_Array_Int(int **p, int Ny, int Nx);
void Free_Memory(void);
int main(int argc, char *argv[])
{
if(argc <3) {
printf("Usage: wham_fep data_file output_wham_file\n");
exit(1);
}
strcpy(szData, argv[1]);
strcpy(szFile_FE, argv[2]);
printf("----------------------------------\n");
printf("Weigthed Histogram Analysis Method\n");
printf("Author: Benoit Roux (1995).\n");
printf("Ported to c by Lei Huang (2012).\n\n");
NPoints = new int[max_wind];
epprtd = Allocate_Mem_2D_Array(max_wind, max_data);
lambda = new double[max_wind];
F = new double[max_wind];
F2 = new double[max_wind];
wham_FEP();
Free_Memory();
return 0;
}
// call WHAM1(maxwind, maxtime, nb_wind, Ntime, epprtd, &
// Lambda, F, F2)
void wham_FEP(void)
{
int i, Time_1, Time_2, Time_3;
double Temp, lambx, eppx;
int Ntot1, Ntot2, ReadItem;
int ioffset=0; // the window used as the reference
FILE *fIn, *fOut;
Ntot1 = Ntot2 = 0;
Temp = 300.0;
kbt=KBOLTZ*Temp;
nb_wind = 0;
NPoints[0] = 0;
lambda[0] = 0.0;
fIn = fopen(szData, "r");
if(fIn == NULL) {
printf("Fail to open file: %s\nQuit\n", szData);
Free_Memory();
exit(1);
}
while(1) {
ReadItem = fscanf(fIn, "%lf%lf", &lambx, &eppx);
if(ReadItem != 2) {
break;
}
if( lambx != lambda[nb_wind] ) {
nb_wind++;
if(nb_wind > max_wind) {
printf("Number of windows exceeds limit.\nQuit\n");
exit(1);
}
NPoints[nb_wind] = 0;
if(Ntot1 > Ntot2) Ntot2=Ntot1;
Ntot1 = 0;
lambda[nb_wind] = lambx;
}
Ntot1 ++;
if(NPoints[nb_wind] < max_data) {
epprtd[nb_wind][NPoints[nb_wind]] = eppx;
NPoints[nb_wind] = NPoints[nb_wind] + 1;
}
}
fclose(fIn);
if(Ntot2 > max_data) {
printf("Some data points have been left out.\n");
}
else {
printf("All data points have been read.\n");
}
printf("Window #_of_Data Lambda\n");
for(i=0; i<=nb_wind; i++) {
printf("%6d %10d %.5lf\n", i+1, NPoints[i], lambda[i]);
F[i] = 0.0;
F2[i] = 0.0;
}
// Time_1 = time(NULL);
// wham(); // the original wham by Benoit Roux
// Time_2 = time(NULL);
// printf("Ellapsed time %d seconds in wham().\n", Time_2-Time_1);
// printf("\n\nWindow #_of_Data Lambda F\n");
// for(i=0; i<=nb_wind; i++) {
// printf(" %-d %10d %.5lf %.5lf\n", i+1, NPoints[i], lambda[i], F2[i]-F2[ioffset]);
// }
Time_2 = time(NULL);
wham_E_Histogram(); // loop over the histogram
Time_3 = time(NULL);
printf("\nEllapsed time %d seconds in wham().\n", Time_3-Time_2);
printf("\n\nWindow #_of_Data Lambda F\n");
for(i=0; i<=nb_wind; i++) {
printf(" %4d %10d %.5lf %.5lf\n", i+1, NPoints[i], lambda[i], F2[i]-F2[ioffset]);
}
fOut = fopen(szFile_FE, "w");
fprintf(fOut, " 100 %.5lf\n", F2[nb_wind]-F2[0]);
fclose(fOut);
}
void wham(void)
{
int i, j, k, t, Converged=0, icycle;
double arg1, arg2, argmax=0.0, Bot_i, Top_i, diff, *pDataTmp, kbt_Inv;
kbt_Inv = 1.0/kbt;
pDataTmp = new double[nb_wind+1];
for(icycle=1; icycle<=NCYCLE; icycle++) {
for(k=0; k<=nb_wind; k++) {
F[k]=0.0;
for(i=0; i<=nb_wind; i++) {
for(t=0; t<NPoints[i]; t++) {
arg1 = (-lambda[k]*epprtd[i][t])*kbt_Inv;
argmax = arg1;
for(j=0; j<=nb_wind; j++) {
arg2 = (F2[j]-lambda[j]*epprtd[i][t])*kbt_Inv;
if(arg2 > argmax) argmax = arg2;
pDataTmp[j] = arg2;
}
Top_i = exp(arg1-argmax);
Bot_i = 0.0;
for(j=0; j<=nb_wind; j++) {
arg2 = pDataTmp[j]-argmax;
Bot_i = Bot_i + NPoints[j] * exp(arg2);
}
F[k] = F[k] + Top_i / Bot_i;
}
}
}
Converged = 1;
for(k=0; k<=nb_wind; k++) {
F[k] = -kbt*log( F[k] );
// printf("window %d: F(k) = %.5lf\n", k+1, F[k]);
diff = fabs( F2[k] - F[k] );
F2[k] = F[k] - F[0];
if(diff > TOL) Converged = 0;
}
if(Converged) {
printf("\nConverged at step: %d\n", icycle);
delete []pDataTmp;
return;
}
}
printf("\nFail to converge in %d steps.\n", NCYCLE);
delete []pDataTmp;
}
#define E_BIN_SIZE (0.0004)
//#define E_BIN_SIZE (0.0001)
void wham_E_Histogram(void)
{
int i, j, k, t, Converged=0, icycle, Idx;
double arg1, arg2, argmax=0.0, Bot_i, Top_i, diff, *pDataTmp, kbt_Inv, E_Local;
double *pEmin=NULL, *pEmax=NULL, **pE_Hist=NULL;
int *pN_Bin=NULL, **nHist_E=NULL;
//start to build the histogram of E for each window and free the memory for all data points, epprtd[][]
pEmin = new double[nb_wind+1];
CHECK_POINTER(pEmin)
pEmax = new double[nb_wind+1];
CHECK_POINTER(pEmax)
pN_Bin = new int[nb_wind+1];
CHECK_POINTER(pN_Bin)
nHist_E = new int*[nb_wind+1];
CHECK_POINTER(nHist_E)
pE_Hist = new double*[nb_wind+1];
CHECK_POINTER(pE_Hist)
for(i=0; i<=nb_wind; i++) {
pEmin[i] = 1.0E100;
pEmax[i] = -1.0E100;
for(j=0; j<NPoints[i]; j++) {
if(epprtd[i][j] > pEmax[i]) {
pEmax[i] = epprtd[i][j];
}
if(epprtd[i][j] < pEmin[i]) {
pEmin[i] = epprtd[i][j];
}
}
pN_Bin[i] = (int)((pEmax[i]-pEmin[i])/E_BIN_SIZE)+1;
nHist_E[i] = new int[pN_Bin[i]];
CHECK_POINTER(nHist_E[i])
pE_Hist[i] = new double[pN_Bin[i]];
CHECK_POINTER(pE_Hist[i])
memset(nHist_E[i], 0, sizeof(int)*pN_Bin[i]);
for(j=0; j<pN_Bin[i]; j++) { // assign the list of energies histogram
pE_Hist[i][j] = pEmin[i] + j*E_BIN_SIZE;
}
for(j=0; j<NPoints[i]; j++) {
Idx = (int)((epprtd[i][j] - pEmin[i])/E_BIN_SIZE);
nHist_E[i][Idx]++;
}
}
Deallocate_Mem_2D_Array(epprtd, max_wind, max_data);
epprtd = NULL;
//end to build the histogram of E for each window and free the memory for all data points, epprtd[][]
kbt_Inv = 1.0/kbt;
pDataTmp = new double[nb_wind+1];
for(icycle=1; icycle<=NCYCLE; icycle++) {
for(k=0; k<=nb_wind; k++) {
F[k]=0.0;
for(i=0; i<=nb_wind; i++) {
for(t=0; t<pN_Bin[i]; t++) {
if(nHist_E[i][t] == 0) {
continue;
}
E_Local = pE_Hist[i][t];
arg1 = (-lambda[k]*E_Local)*kbt_Inv;
argmax = arg1;
for(j=0; j<=nb_wind; j++) {
arg2 = (F2[j]-lambda[j]*E_Local)*kbt_Inv;
if(arg2 > argmax) argmax = arg2;
pDataTmp[j] = arg2;
}
Top_i = exp(arg1-argmax) * nHist_E[i][t];
Bot_i = 0.0;
for(j=0; j<=nb_wind; j++) {
arg2 = pDataTmp[j]-argmax;
Bot_i = Bot_i + NPoints[j] * exp(arg2);
}
F[k] = F[k] + Top_i / Bot_i;
}
}
}
Converged = 1;
for(k=0; k<=nb_wind; k++) {
F[k] = -kbt*log( F[k] );
// printf("window %d: F(k) = %.5lf\n", k+1, F[k]);
diff = fabs( F2[k] - F[k] );
F2[k] = F[k] - F[0];
if(diff > TOL) Converged = 0;
}
if(Converged) {
printf("\nConverged at step: %d\n", icycle);
delete []pDataTmp;
for(i=0; i<=nb_wind; i++) {
delete [](nHist_E[i]);
delete [](pE_Hist[i]);
}
delete []nHist_E;
delete []pE_Hist;
delete []pEmin;
delete []pEmax;
delete []pN_Bin;
return;
}
}
printf("\nFail to converge in %d steps.\n", NCYCLE);
delete []pDataTmp;
for(i=0; i<=nb_wind; i++) {
delete [](nHist_E[i]);
delete [](pE_Hist[i]);
}
delete []nHist_E;
delete []pE_Hist;
delete []pEmin;
delete []pEmax;
delete []pN_Bin;
return;
}
#undef E_BIN_SIZE
double** Allocate_Mem_2D_Array(int Ny, int Nx)
{
double **p;
int i;
p = new double*[Ny];
if(p == NULL) {
printf("Fail to allocate memory in Allocate_Mem_2D_Array().\nQuit\n");
exit(1);
}
for(i=0; i<Ny; i++) {
p[i] = new double[Nx];
if(p[i] == NULL) {
printf("Fail to allocate memory in Allocate_Mem_2D_Array().\nQuit\n");
exit(1);
}
}
return p;
}
void Deallocate_Mem_2D_Array(double **p, int Ny, int Nx)
{
int i;
for(i=0; i<Ny; i++) {
delete [](p[i]);
}
delete []p;
p=NULL;
}
int** Allocate_Mem_2D_Array_Int(int Ny, int Nx)
{
int **p;
int i;
p = new int*[Ny];
if(p == NULL) {
printf("Fail to allocate memory in Allocate_Mem_2D_Array_Int().\nQuit\n");
exit(1);
}
for(i=0; i<Ny; i++) {
p[i] = new int[Nx];
if(p[i] == NULL) {
printf("Fail to allocate memory in Allocate_Mem_2D_Array_Int().\nQuit\n");
exit(1);
}
}
return p;
}
void Deallocate_Mem_2D_Array_Int(int **p, int Ny, int Nx)
{
int i;
for(i=0; i<Ny; i++) {
delete [](p[i]);
}
delete []p;
p=NULL;
}
void Free_Memory(void)
{
if(epprtd) {
Deallocate_Mem_2D_Array(epprtd, max_wind, max_data);
}
if(NPoints) delete []NPoints;
if(lambda) delete []lambda;
if(F) delete []F;
if(F2) delete []F2;
}