/* Metropolis Monte Carlo simulation of a Lennard-Jones fluid in a periodic boundary using the modified pair potential U(r,\lambda) = 4(\lambda^5 r^{-12} - \lambda^3 r^{-6}) for all pairs involving atom N-1; to calculate the ensemble average of \frac{\partial U}{\partial\lambda} for use in thermodynamic integration. Cameron F. Abrams Written for the course CHE 800-002, Molecular Simulation Spring 0304 compile using "gcc -o mclj_ti mclj_ti.c -lm -lgsl" (assumes the GNU Scientific Library is installed) runs as "./mclj -N -rho \ -nc -dr \ -s -ne <#equil.cycles(100)>" You must have the GNU Scientific Library installed; see the coursenotes to learn how to do this. Drexel University, Department of Chemical Engineering Philadelphia (c) 2004 */ #include #include #include #include /* An N^2 algorithm for computing the total energy. The virial is also computed and returned in *vir. is also accumulated in *dudl */ double total_e ( double * rx, double * ry, double * rz, int N, double L, double rc2, double lambda, int tailcorr, double ecor, int shift, double ecut, double ecut_l, double decutdl, double * vir, double * dudl ) { int i,j; double dx, dy, dz, r2, r6i; double e = 0.0, hL=L/2.0; double l2=lambda*lambda; double l3=l2*lambda; double l4=l3*lambda; double l5=l4*lambda; *vir=*dudl=0.0; for (i=0;i<(N-1);i++) { for (j=i+1;jhL) dx-=L; else if (dx<-hL) dx+=L; if (dy>hL) dy-=L; else if (dy<-hL) dy+=L; if (dz>hL) dz-=L; else if (dz<-hL) dz+=L; r2 = dx*dx + dy*dy + dz*dz; if (r2L) 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,lambda,tailcorr,ecor, shift,ecut,ecut_l,decutdl,&vir,&dudl); /* Conditionally accept... */ if (gsl_rng_uniform(r) < exp(-T*(E_new-E_old))) { E_old=E_new; vir_old=vir; dudl_old=dudl; 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) { esum+=E_old; vir_sum+=vir_old; dudl_sum+=dudl_old; nSamp++; } } if (short_out) fprintf(stdout,"%.5lf %.5lf\n",lambda,dudl_sum/nSamp); else fprintf(stdout,"NVT Metropolis Monte Carlo Simulation" " of the Lennard-Jones fluid w/ lambda-potential\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" "Lambda: %.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" ": %.5lf\n" "Program ends.\n", N,nCycles,sqrt(rc2),dr,rho,1.0/T,lambda, 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), dudl_sum/nSamp); }