int main ( int argc, char * argv[] ) { double * rx, * ry, * rz; double * vx, * vy, * vz; double * fx, * fy, * fz; int * ix, * iy, * iz; int nl; double * xi, * vxi, * Q; int N=216,c,a; double L=0.0; double rho=0.5, Tb = 1.0, nu=1.0, rc2 = 1.e20; double vir, vir_sum, pcor, V; double PE, KE, TE, ecor, ecut, T0=0.0, TE0; double rr3,dt=0.001, dt2, dt_2, dt_4, dt_8, sigma; int tj_ts=-1; double tj_Tb=1.0; int i,j,s; int nSteps = 10, fSamp=100; int short_out=0; int use_e_corr=0; int unfold = 0; char fn[20]; FILE * out; char * wrt_code_str = "w"; char * init_cfg_file = NULL; gsl_rng * r = gsl_rng_alloc(gsl_rng_mt19937); unsigned long int Seed = 23410981; /* Allocate arrays for the NH Chain */ nl = 2; /* for now... */ xi = (double*)malloc(nl*sizeof(double)); vxi = (double*)malloc(nl*sizeof(double)); Q = (double*)malloc(nl*sizeof(double)); /* Default masses */ Q[0] = Q[1] = 0.1; /* Here we parse the command line arguments; If you add an option, document it in the usage() function! */ for (i=1;i<argc;i++) { if (!strcmp(argv[i],"-N")) N=atoi(argv[++i]); else if (!strcmp(argv[i],"-rho")) rho=atof(argv[++i]); else if (!strcmp(argv[i],"-nu")) nu=atof(argv[++i]); else if (!strcmp(argv[i],"-dt")) dt=atof(argv[++i]); else if (!strcmp(argv[i],"-rc")) rc2=atof(argv[++i]); else if (!strcmp(argv[i],"-ns")) nSteps = atoi(argv[++i]); else if (!strcmp(argv[i],"-so")) short_out=1; else if (!strcmp(argv[i],"-T0")) T0=atof(argv[++i]); else if (!strcmp(argv[i],"-Tb")) Tb=atof(argv[++i]); else if (!strcmp(argv[i],"-Q")) sscanf(argv[++i],"%lf,%lf", &Q[0],&Q[1]); else if (!strcmp(argv[i],"-Tjump")) sscanf(argv[++i],"%i,%lf", &tj_ts,&tj_Tb); else if (!strcmp(argv[i],"-fs")) fSamp=atoi(argv[++i]); else if (!strcmp(argv[i],"-sf")) wrt_code_str = argv[++i]; else if (!strcmp(argv[i],"-icf")) init_cfg_file = argv[++i]; else if (!strcmp(argv[i],"-ecorr")) use_e_corr = 1; else if (!strcmp(argv[i],"-seed")) Seed = (unsigned long)atoi(argv[++i]); else if (!strcmp(argv[i],"-uf")) unfold = 1; else if (!strcmp(argv[i],"-h")) { usage(); exit(0); } else { fprintf(stderr,"Error: Command-line argument '%s' not recognized.\n", argv[i]); exit(-1); } } /* Compute the side-length */ L = pow((V=N/rho),0.3333333); /* Compute the tail-corrections; assumes sigma and epsilon are both 1 */ rr3 = 1.0/(rc2*rc2*rc2); ecor = use_e_corr?8*M_PI*rho*(rr3*rr3*rr3/9.0-rr3/3.0):0.0; pcor = use_e_corr?16.0/3.0*M_PI*rho*rho*(2./3.*rr3*rr3*rr3-rr3):0.0; ecut = 4*(rr3*rr3*rr3*rr3-rr3*rr3); /* Compute the *squared* cutoff, reusing the variable rc2 */ rc2*=rc2; /* compute the squared time step */ dt2 = dt*dt; dt_2 = 0.5*dt; dt_4 = 0.5*dt_2; dt_8 = 0.5*dt_4; // thanks, [email protected] /* Compute sigma */ sigma = sqrt(Tb); /* Output some initial information */ fprintf(stdout,"# Nose-Hoover-Chain-Thermostat MD Simulation" " of a Lennard-Jones fluid\n"); fprintf(stdout,"# L = %.5lf; rho = %.5lf; N = %i; rc = %.5lf\n", L,rho,N,sqrt(rc2)); fprintf(stdout,"# nSteps %i, seed %d, dt %.5lf, " "Tb %.5lf, Q0 %.5lf Q1 %.5lf\n", nSteps,Seed,dt,Tb,Q[0],Q[1]); /* Seed the random number generator */ gsl_rng_set(r,Seed); /* Allocate the position arrays */ rx = (double*)malloc(N*sizeof(double)); ry = (double*)malloc(N*sizeof(double)); rz = (double*)malloc(N*sizeof(double)); /* Allocate the boundary crossing counter arrays */ ix = (int*)malloc(N*sizeof(int)); iy = (int*)malloc(N*sizeof(int)); iz = (int*)malloc(N*sizeof(int)); /* Allocate the velocity arrays */ vx = (double*)malloc(N*sizeof(double)); vy = (double*)malloc(N*sizeof(double)); vz = (double*)malloc(N*sizeof(double)); /* Allocate the force arrays */ fx = (double*)malloc(N*sizeof(double)); fy = (double*)malloc(N*sizeof(double)); fz = (double*)malloc(N*sizeof(double)); /* Generate initial positions on a cubic grid, and measure initial energy */ init(rx,ry,rz,vx,vy,vz,ix,iy,iz,N,xi,vxi,nl,L,r,T0,&KE,init_cfg_file); sprintf(fn,"%i.xyz",0); out=fopen(fn,"w"); xyz_out(out,rx,ry,rz, vx,vy,vz,ix,iy,iz, L,N, xi,vxi,Q,nl, 16,1,unfold); fclose(out); PE = total_e(rx,ry,rz,fx,fy,fz,N,L,rc2,ecor,ecut,&vir); TE0=PE+KE; fprintf(stdout,"# step PE KE TE drift T P\n"); /* Nose-Hoover-Chain (Algorithms 30, 31, 32) */ for (s=0;s<nSteps;s++) { /* do a temperature jump at the prescribed time */ if (s==tj_ts) Tb = tj_Tb; chain(&KE,dt,dt_2,dt_4,dt_8,Q,xi,vxi,vx,vy,vz,nl,N,Tb); /* First integration half-step */ KE = 0.0; for (i=0;i<N;i++) { rx[i]+=vx[i]*dt_2; ry[i]+=vy[i]*dt_2; rz[i]+=vz[i]*dt_2; /* Apply periodic boundary conditions */ if (rx[i]<0.0) { rx[i]+=L; ix[i]--; } if (rx[i]>L) { rx[i]-=L; ix[i]++; } if (ry[i]<0.0) { ry[i]+=L; iy[i]--; } if (ry[i]>L) { ry[i]-=L; iy[i]++; } if (rz[i]<0.0) { rz[i]+=L; iz[i]--; } if (rz[i]>L) { rz[i]-=L; iz[i]++; } } /* Calculate forces */ PE = total_e(rx,ry,rz,fx,fy,fz,N,L,rc2,ecor,ecut,&vir); /* Second integration half-step */ for (i=0;i<N;i++) { vx[i]+=dt*fx[i]; vy[i]+=dt*fy[i]; vz[i]+=dt*fz[i]; rx[i]+=vx[i]*dt_2; ry[i]+=vy[i]*dt_2; rz[i]+=vz[i]*dt_2; KE+=vx[i]*vx[i]+vy[i]*vy[i]+vz[i]*vz[i]; } KE*=0.5; chain(&KE,dt,dt_2,dt_4,dt_8,Q,xi,vxi,vx,vy,vz,nl,N,Tb); TE=PE+KE; fprintf(stdout,"%i %.5lf %.5lf %.5lf %.5lf %.5le %.5lf %.5lf\n", s,s*dt,PE,KE,TE,(TE-TE0)/TE0,KE*2/3./N,rho*KE*2./3./N+vir/3.0/V); if (!(s%fSamp)) { sprintf(fn,"%i.xyz",!strcmp(wrt_code_str,"a")?0:s); out=fopen(fn,wrt_code_str); xyz_out(out,rx,ry,rz,vx,vy,vz,ix,iy,iz,L,N,xi,vxi,Q,nl,16,1,unfold); fclose(out); } } }
int main ( int argc, char * argv[] ) { double * rx, * ry, * rz; double * vx, * vy, * vz; double * fx, * fy, * fz; int * ix, * iy, * iz; int N=216,c,a; double L=0.0; double rho=0.5, Tb = 1.0, gamma=1.0, rc2 = 2.5; double vir, vir_sum, pcor, V; double PE, KE, TE, ecor, ecut, T0=0.0, TE0; double rr3,dt=0.001, dt2, gfric, noise; int i,j,s; int nSteps = 10, fSamp=100; int short_out=0; int use_e_corr=0; int unfold = 0; char fn[20]; FILE * out; char * wrt_code_str = "w"; char * init_cfg_file = NULL; gsl_rng * r = gsl_rng_alloc(gsl_rng_mt19937); unsigned long int Seed = 23410981; /* Here we parse the command line arguments; If you add an option, document it in the usage() function! */ for (i=1;i<argc;i++) { if (!strcmp(argv[i],"-N")) N=atoi(argv[++i]); else if (!strcmp(argv[i],"-rho")) rho=atof(argv[++i]); else if (!strcmp(argv[i],"-gam")) gamma=atof(argv[++i]); else if (!strcmp(argv[i],"-dt")) dt=atof(argv[++i]); else if (!strcmp(argv[i],"-rc")) rc2=atof(argv[++i]); else if (!strcmp(argv[i],"-ns")) nSteps = atoi(argv[++i]); else if (!strcmp(argv[i],"-so")) short_out=1; else if (!strcmp(argv[i],"-T0")) T0=atof(argv[++i]); else if (!strcmp(argv[i],"-Tb")) Tb=atof(argv[++i]); else if (!strcmp(argv[i],"-fs")) fSamp=atoi(argv[++i]); else if (!strcmp(argv[i],"-sf")) wrt_code_str = argv[++i]; else if (!strcmp(argv[i],"-icf")) init_cfg_file = argv[++i]; else if (!strcmp(argv[i],"-ecorr")) use_e_corr = 1; else if (!strcmp(argv[i],"-seed")) Seed = (unsigned long)atoi(argv[++i]); else if (!strcmp(argv[i],"-uf")) unfold = 1; else if (!strcmp(argv[i],"-h")) { usage(); exit(0); } else { fprintf(stderr,"Error: Command-line argument '%s' not recognized.\n", argv[i]); exit(-1); } } /* Compute the side-length */ L = pow((V=N/rho),0.3333333); /* Compute the tail-corrections; assumes sigma and epsilon are both 1 */ rr3 = 1.0/(rc2*rc2*rc2); ecor = use_e_corr?8*M_PI*rho*(rr3*rr3*rr3/9.0-rr3/3.0):0.0; pcor = use_e_corr?16.0/3.0*M_PI*rho*rho*(2./3.*rr3*rr3*rr3-rr3):0.0; ecut = 4*(rr3*rr3*rr3*rr3-rr3*rr3); /* Compute the *squared* cutoff, reusing the variable rc2 */ rc2*=rc2; /* compute the squared time step */ dt2=dt*dt; /* Compute gfric */ gfric = 1.0-gamma*dt/2.0; /* Compute noise */ noise = sqrt(6.0*gamma*Tb/dt); /* Output some initial information */ fprintf(stdout,"# Langevin-Thermostat MD Simulation" " of a Lennard-Jones fluid\n"); fprintf(stdout,"# L = %.5lf; rho = %.5lf; N = %i; rc = %.5lf\n", L,rho,N,sqrt(rc2)); fprintf(stdout,"# nSteps %i, seed %d, dt %.5lf, T0 %.5lf, gamma %.5lf\n", nSteps,Seed,dt,T0,gamma); fprintf(stdout,"# gfric %.5lf noise %.5lf\n",gfric,noise); /* Seed the random number generator */ gsl_rng_set(r,Seed); /* Allocate the position arrays */ rx = (double*)malloc(N*sizeof(double)); ry = (double*)malloc(N*sizeof(double)); rz = (double*)malloc(N*sizeof(double)); /* Allocate the boundary crossing counter arrays */ ix = (int*)malloc(N*sizeof(int)); iy = (int*)malloc(N*sizeof(int)); iz = (int*)malloc(N*sizeof(int)); /* Allocate the velocity arrays */ vx = (double*)malloc(N*sizeof(double)); vy = (double*)malloc(N*sizeof(double)); vz = (double*)malloc(N*sizeof(double)); /* Allocate the force arrays */ fx = (double*)malloc(N*sizeof(double)); fy = (double*)malloc(N*sizeof(double)); fz = (double*)malloc(N*sizeof(double)); /* Generate initial positions on a cubic grid, and measure initial energy */ init(rx,ry,rz,vx,vy,vz,ix,iy,iz,N,L,r,T0,&KE,init_cfg_file); sprintf(fn,"%i.xyz",0); out=fopen(fn,"w"); xyz_out(out,rx,ry,rz,vx,vy,vz,ix,iy,iz,L,N,16,1,unfold); fclose(out); PE = total_e(rx,ry,rz,fx,fy,fz,N,L,rc2,ecor,ecut,&vir); TE0=PE+KE; fprintf(stdout,"# step time PE KE TE drift T P\n"); for (s=0;s<nSteps;s++) { /* First integration half-step */ for (i=0;i<N;i++) { rx[i] += vx[i]*dt+0.5*dt2*fx[i]; ry[i] += vy[i]*dt+0.5*dt2*fy[i]; rz[i] += vz[i]*dt+0.5*dt2*fz[i]; vx[i] = vx[i]*gfric + 0.5*dt*fx[i]; vy[i] = vy[i]*gfric + 0.5*dt*fy[i]; vz[i] = vz[i]*gfric + 0.5*dt*fz[i]; /* Apply periodic boundary conditions */ if (rx[i]<0.0) { rx[i]+=L; ix[i]--; } if (rx[i]>L) { rx[i]-=L; ix[i]++; } if (ry[i]<0.0) { ry[i]+=L; iy[i]--; } if (ry[i]>L) { ry[i]-=L; iy[i]++; } if (rz[i]<0.0) { rz[i]+=L; iz[i]--; } if (rz[i]>L) { rz[i]-=L; iz[i]++; } } /* Calculate forces */ /* Initialize forces */ for (i=0;i<N;i++) { fx[i] = 2*noise*(gsl_rng_uniform(r)-0.5); fy[i] = 2*noise*(gsl_rng_uniform(r)-0.5); fz[i] = 2*noise*(gsl_rng_uniform(r)-0.5); } PE = total_e(rx,ry,rz,fx,fy,fz,N,L,rc2,ecor,ecut,&vir); /* Second integration half-step */ KE = 0.0; for (i=0;i<N;i++) { vx[i] = vx[i]*gfric + 0.5*dt*fx[i]; vy[i] = vy[i]*gfric + 0.5*dt*fy[i]; vz[i] = vz[i]*gfric + 0.5*dt*fz[i]; KE+=vx[i]*vx[i]+vy[i]*vy[i]+vz[i]*vz[i]; } KE*=0.5; TE=PE+KE; fprintf(stdout,"%i %.5lf %.5lf %.5lf %.5lf %.5le %.5lf %.5lf\n", s,s*dt,PE,KE,TE,(TE-TE0)/TE0,KE*2/3./N,rho*KE*2./3./N+vir/3.0/V); if (!(s%fSamp)) { sprintf(fn,"%i.xyz",!strcmp(wrt_code_str,"a")?0:s); out=fopen(fn,wrt_code_str); xyz_out(out,rx,ry,rz,vx,vy,vz,ix,iy,iz,L,N,16,1,unfold); fclose(out); } } }
int main ( int argc, char * argv[] ) { double * rx, * ry, * rz; int N=216,c; double L=0.0; double rho=0.5, T=1.0, rc2 = 1.e20, vir, vir_old, vir_sum, pcor, V; double E_new, E_old, esum, rr3, ecor, ecut; double we, w_sum=0.0; double dr=0.1,dx,dy,dz; double rxold,ryold,rzold; int i,j,fs=1; int nCycles = 10, nSamp, nEq=1000; int nAcc; int short_out=0; int shift=0; int tailcorr=1; gsl_rng * r = gsl_rng_alloc(gsl_rng_mt19937); unsigned long int Seed = 23410981; /* Here we parse the command line arguments */ for (i=1;i<argc;i++) { if (!strcmp(argv[i],"-N")) N=atoi(argv[++i]); else if (!strcmp(argv[i],"-rho")) rho=atof(argv[++i]); else if (!strcmp(argv[i],"-T")) T=atof(argv[++i]); else if (!strcmp(argv[i],"-dr")) dr=atof(argv[++i]); else if (!strcmp(argv[i],"-rc")) rc2=atof(argv[++i]); else if (!strcmp(argv[i],"-nc")) nCycles = atoi(argv[++i]); else if (!strcmp(argv[i],"-ne")) nEq = atoi(argv[++i]); else if (!strcmp(argv[i],"-fs")) fs = atoi(argv[++i]); else if (!strcmp(argv[i],"-so")) short_out=1; else if (!strcmp(argv[i],"+tc")) tailcorr=0; else if (!strcmp(argv[i],"-sh")) shift=1; else if (!strcmp(argv[i],"-seed")) Seed = (unsigned long)atoi(argv[++i]); else { fprintf(stderr,"Error. Argument '%s' is not recognized.\n", argv[i]); exit(-1); } } /* Compute the side-length */ L = pow((V=N/rho),0.3333333); /* Compute the tail-corrections; assumes sigma and epsilon are both 1 */ rr3 = 1.0/(rc2*rc2*rc2); ecor = 8*M_PI*rho*(rr3*rr3*rr3/9.0-rr3/3.0); pcor = 16.0/3.0*M_PI*rho*rho*(2./3.*rr3*rr3*rr3-rr3); ecut = 4*(rr3*rr3*rr3*rr3-rr3*rr3); /* Compute the *squared* cutoff, reusing the variable rc2 */ rc2*=rc2; /* For computational efficiency, use reciprocal T */ T = 1.0/T; /* compute box volume */ V = L*L*L; /* Output some initial information */ fprintf(stdout,"# NVT MC Simulation of a Lennard-Jones fluid\n"); fprintf(stdout,"# L = %.5lf; rho = %.5lf; N = %i; rc = %.5lf\n", L,rho,N,sqrt(rc2)); fprintf(stdout,"# T = %.5lf\n",1.0/T); fprintf(stdout,"# nCycles %i, nEq %i, seed %d, dR %.5lf\n", nCycles,nEq,Seed,dr); /* Total number of cycles is number of "equilibration" cycles plus number of "production" cycles */ nCycles+=nEq; /* Seed the random number generator */ gsl_rng_set(r,Seed); /* Allocate the position arrays */ rx = (double*)malloc((N+1)*sizeof(double)); ry = (double*)malloc((N+1)*sizeof(double)); rz = (double*)malloc((N+1)*sizeof(double)); /* Generate initial positions on a cubic grid, and measure initial energy */ init(rx,ry,rz,N,L,r); E_old = total_e(rx,ry,rz,N,L,rc2,tailcorr,ecor,shift,ecut,&vir_old); nAcc = 0; esum = 0.0; nSamp = 0; vir_sum = 0.0; for (c=0;c<nCycles;c++) { /* Randomly select a particle */ i=(int)gsl_rng_uniform_int(r,N); /* calculate displacement */ dx = dr*(0.5-gsl_rng_uniform(r)); dy = dr*(0.5-gsl_rng_uniform(r)); dz = dr*(0.5-gsl_rng_uniform(r)); /* Save the current position of particle i */ rxold=rx[i]; ryold=ry[i]; rzold=rz[i]; /* Displace particle i */ rx[i]+=dx; ry[i]+=dy; rz[i]+=dz; /* Apply periodic boundary conditions */ if (rx[i]<0.0) rx[i]+=L; if (rx[i]>L) rx[i]-=L; if (ry[i]<0.0) ry[i]+=L; if (ry[i]>L) ry[i]-=L; if (rz[i]<0.0) rz[i]+=L; if (rz[i]>L) rz[i]-=L; /* Get the new energy */ E_new = total_e(rx,ry,rz,N,L,rc2,tailcorr,ecor,shift,ecut,&vir); /* Conditionally accept... */ if (gsl_rng_uniform(r) < exp(-T*(E_new-E_old))) { E_old=E_new; vir_old=vir; nAcc++; } /* ... or reject the move; reassign the old positions */ else { rx[i]=rxold; ry[i]=ryold; rz[i]=rzold; } /* Sample: default frequency is once per trial move; We must include results of a move regardless of whether the move is accepted or rejected. */ if (c>nEq&&(!(c%fs))) { esum+=E_old; vir_sum+=vir_old; widom(rx,ry,rz,N,L,rc2,shift,ecut,r,&we); w_sum+=exp(-T*we); nSamp++; } } if (short_out) fprintf(stdout,"%.5lf %.5lf\n",rho, -log(w_sum/nSamp)/T + (tailcorr?(2*ecor):0)); else fprintf(stdout,"NVT Metropolis Monte Carlo Simulation" " of the Lennard-Jones fluid with the Widom Method.\n" "---------------------------------------------\n" "Number of particles: %i\n" "Number of cycles: %i\n" "Cutoff radius: %.5lf\n" "Maximum displacement: %.5lf\n" "Density: %.5lf\n" "Temperature: %.5lf\n" "Tail corrections applied? %s\n" "Shifted potential? %s\n" "Results:\n" "Potential energy tail correction: %.5lf\n" "Pressure tail correction: %.5lf\n" "Potential energy shift at cutoff: %.5lf\n" "Acceptance ratio: %.5lf\n" "Energy/particle: %.5lf\n" "Ideal gas pressure: %.5lf\n" "Virial: %.5lf\n" "Total pressure: %.5lf\n" "Excess chemical potential: %.5lf\n" "Program ends.\n", N,nCycles,sqrt(rc2),dr,rho,1.0/T, tailcorr?"Yes":"No",shift?"Yes":"No", ecor,pcor,ecut, ((double)nAcc)/nCycles, esum/nSamp/N, rho/T,vir_sum/3.0/nSamp/V, vir_sum/3.0/nSamp/V+rho/T+(tailcorr?pcor:0.0), -log(w_sum/nSamp)/T + (tailcorr?(2*ecor):0)); }