- #include <stdio.h>
- #include <math.h>
- #include <stdlib.h>
- #include <time.h>
- #include <string.h>
- #define nDim 3
- #define sigma 3.4e-10
- #define epsilon 1.65e-21
- #define masskg 6.6e-26
-
- double random1();
- double maxwell();
- double gauss(double std, double mean );
- void velscaler(double *velocity, double T, int n);
- void initialization(double *positions, double *velocities, int n, double L, double T);
- int neighborhood(double *position, int *celllist, int n, double L, double rcut);
- void LJ_Forces( double *force, double *potential, double *position, int n, int Nmax, int *celllist, double L, double rcut, double rmax, double *px);
- void andersen(int switch1, int n, double *force, double *velocity, double *positions,double *tracer, double dt, double T, double L, int *blinker );
- void properties(double *position, double *tracer, double *velocities, double *forces, double *potential, int n, double *U, double *KE, double *energy, double *avevel, double *Temp, double *px, double *pressure, double v, double rcut, double rho, double L, double *Ds, double timecount);
- void position_printer(FILE * fp, double * positions, int n, int *blinker, double L, int flag);
- void velocity_printer(FILE *fp, double * velocity, int n );
-
- main() {
- int n, i, j, ncel, *link, *celllist, *neighborlist, nMax, neighborcounter, cycles, track, *blinker;
- double Rho, T, dt, dt_squared, L, vol, mass, ndouble, *positions, *velocities, rcut, *force;
- double rcel, *potential, kb, kT, *acceleration, Lcell, rmax, timecounter, error, v, U, totale;
- double *energies, KE, *avevel, Temp, *forcematrix, pressure, *pix, *tracer, Ds, tau, *forcestore;
- double squarevel[3], aveke, avepe, avetotal, aveT, aveP, aveDs;
- double andersentime,veltime, codetime,productiontime, inittime;
- char buffer[50], vyes[20];
- char yes[20];
- FILE * fp;
- FILE * tracker;
- FILE * melter;
- FILE * velocityfp;
- FILE * OUT;
- clock_t codebegin, codeend, initbegin, initend, scalebegin, scaleend, andersenbegin, andersenend;
- clock_t productionbegin, productionend;
- codebegin = clock();
- srandom(time(NULL));
- printf("How many cycles?\n");
- scanf("%d",&cycles);
-
- printf("How many atoms (perfect cube)?\n");
- scanf("%d",&n);
-
- rcut = 2.5;
- rmax = rcut + 1;
- printf("Rho (Lennard-Jones units)?\n");
- scanf("%lf",&Rho);
-
- printf("Temp (Lennard-Jones units)?\n");
- scanf("%lf",&T);
-
- mass = 1;
- tau = sigma*sqrt(masskg/epsilon);
- dt = 1e-15/tau;
- L = pow((double)n / Rho, 0.333333);
- vol = n/Rho;
-
- positions = (double*)malloc(nDim*n*sizeof(double));
- velocities = (double*)malloc(nDim*n*sizeof(double));
- force = (double*)malloc(nDim*n*sizeof(double));
- potential = (double*)malloc(n*sizeof(double));
- neighborlist = (int*)malloc(n*n*sizeof(int));
- avevel = (double*)malloc(nDim*sizeof(double));
- pix = (double*)malloc(nDim*sizeof(double));
- tracer = (double*)malloc(nDim*n*sizeof(double));
- blinker = (int*)malloc(nDim*n*sizeof(int));
- memset(positions,0.0,nDim*n*sizeof(double));
- memset(velocities,0.0,nDim*n*sizeof(double));
- memset(force,0.0,nDim*n*sizeof(double));
- memset(potential,0.0,n*sizeof(double));
- memset(neighborlist,0,n*n*sizeof(int));
- memset(avevel,0.0,3*sizeof(double));
- memset(tracer,0.0,nDim*n*sizeof(double));
- memset(tracer,0.0,nDim*n*sizeof(double));
- memset(blinker,0,nDim*n*sizeof(int));
- OUT = fopen("output","w");
- printf("Would you like to apply an Andersen Thermostat? [Y/N]\n");
- scanf("%s",yes);
- printf("Would you like to Velocity Scale? [Y/N]\n");
- scanf("%s",vyes);
- printf("What particle would you like to track?\n");
- scanf("%d",&track);
- initbegin = clock();
- fp = fopen("Initial.xyz","w");
- velocityfp = fopen("Initialvel","w");
- initialization(positions,velocities,n,L,T);
- velocity_printer(velocityfp,velocities,n);
- position_printer(fp,positions,n,blinker,L,0);
- fclose(fp);
- fclose(velocityfp);
- melter = fopen("Melting.xyz","w");
- position_printer(melter,positions,n, blinker, L,1);
- nMax = neighborhood(positions,neighborlist,n,L,rmax);
- if (nMax == 0 ) {
- return 0;
- }
- LJ_Forces(force,potential,positions,n,nMax,neighborlist,L,rcut,rmax, pix);
- initend = clock();
- inittime = (double)(initend - initbegin) / CLOCKS_PER_SEC;
- timecounter = 0.0;
- neighborcounter = 0;
- if (strcmp(vyes,"Y") == 0) {
- scalebegin = clock();
- printf("\n\nMelting at constant Temp\n\n");
- fprintf(OUT,"\n\nMelting at constant Temp\n\n");
- for(i=0;i<cycles;i++) {
- neighborcounter += 1;
- andersen(1,n,force,velocities,positions,tracer, dt, T, L, blinker);
- LJ_Forces(force,potential,positions,n,nMax,neighborlist,L,rcut,rmax, pix);
- andersen(2,n,force,velocities,positions,tracer,dt, T, L, blinker);
- if (neighborcounter > 10) {
- nMax = neighborhood(positions,neighborlist,n,L,rmax);
- neighborcounter = 0;
- velscaler(velocities,T,n);
- position_printer(melter,positions,n, blinker, L,1);
- }
- timecounter += dt;
- properties(positions,tracer,velocities,force,potential,n,&U,&KE,&totale, avevel, &Temp,pix, &pressure, vol, rcut, Rho, L, &Ds, timecounter);
- printf("%lf %lf %lf %lf %lf %lf %lf\n", timecounter, KE, U, totale, pressure, Ds, Temp);
- fprintf(OUT,"%lf %lf %lf %lf %lf %lf %lf\n", timecounter, KE, U, totale, pressure, Ds, Temp);
- }
- velocityfp = fopen("Meltedvel","w");
- velocity_printer(velocityfp,velocities,n);
- fclose(velocityfp);
- sprintf(buffer,"%lf.xyz",dt*i);
- fp = fopen("melted.xyz","w");
- position_printer(fp,positions,n,blinker,L,0);
- fclose(fp);
- scaleend = clock();
- veltime = (double)(scaleend - scalebegin) / CLOCKS_PER_SEC;
- }
- if( strcmp(yes,"Y") == 0 ) {
- andersenbegin = clock();
- printf("\n\nAndersen Thermostat\n\n");
- fprintf(OUT,"\n\nAndersen Thermostat\n\n");
- velocityfp = fopen("Andersenvel","w");
- neighborcounter = 0;
- for(i=0;i<cycles;i++) {
- neighborcounter += 1;
- andersen(1,n,force,velocities,positions,tracer, dt, T, L, blinker);
- LJ_Forces(force,potential,positions,n,nMax,neighborlist,L,rcut,rmax, pix);
- andersen(3,n,force,velocities,positions,tracer,dt, T, L, blinker);
- if ((i % 10) == 0) {
- nMax = neighborhood(positions,neighborlist,n,L,rmax);
- neighborcounter = 0;
- position_printer(melter,positions,n, blinker, L,1);
- }
- timecounter += dt;
- properties(positions,tracer,velocities,force,potential,n,&U,&KE,&totale, avevel, &Temp,pix, &pressure, vol, rcut, Rho, L, &Ds, timecounter);
- printf("%lf %lf %lf %lf %lf %lf %lf\n", timecounter, KE, U, totale, pressure, Ds, Temp);
- fprintf(OUT,"%lf %lf %lf %lf %lf %lf %lf\n", timecounter, KE, U, totale, pressure, Ds, Temp);
-
- }
- velocity_printer(velocityfp,velocities,n);
- fclose(velocityfp);
- andersenend = clock();
- andersentime = (double)(andersenend - andersenbegin) / CLOCKS_PER_SEC;
- }
-
- productionbegin = clock();
- memset(tracer,0.0,nDim*n*sizeof(double));
- cycles = 10000;
- tracker = fopen("tracking","w");
- fprintf(tracker,"0 0 0\n");
- neighborcounter = 0;
- aveke=avepe=avetotal=aveT=aveP=aveDs=0.0;
- printf("\n\nNVE Production\n\n");
- fprintf(OUT,"\n\nNVE Production\n\n");
- velocityfp = fopen("FinalVel","w");
- for(i=0;i<cycles;i++) {
- timecounter += dt;
- neighborcounter += 1;
- andersen(1,n,force,velocities,positions,tracer,dt, T, L, blinker);
- fprintf(tracker,"%lf %lf %lf\n", *(tracer + track), *(tracer + n + track), *(tracer + 2*n + track));
- LJ_Forces(force,potential,positions,n,nMax,neighborlist,L,rcut,rmax,pix);
- andersen(2,n,force,velocities,positions,tracer,dt, T, L, blinker);
- if ((i % 10) == 0) {
- nMax = neighborhood(positions,neighborlist,n,L,rmax);
- neighborcounter = 0;
- position_printer(melter,positions,n, blinker, L,1);
- }
- timecounter += dt;
- properties(positions,tracer,velocities,force,potential,n,&U,&KE,&totale, avevel, &Temp,pix, &pressure, vol, rcut, Rho, L, &Ds, timecounter);
- printf("%lf %lf %lf %lf %lf %lf %lf\n", timecounter, KE, U, totale, pressure, Ds, Temp);
- fprintf(OUT,"%lf %lf %lf %lf %lf %lf %lf\n", timecounter, KE, U, totale, pressure, Ds, Temp);
- aveke += KE;
- avepe += U;
- avetotal += totale;
- aveP += pressure;
- aveT += Temp;
- aveDs += Ds;
- }
- productionend = clock();
- productiontime = (double)(productionend - productionbegin) / CLOCKS_PER_SEC;
- velocity_printer(velocityfp,velocities,n);
- fclose(velocityfp);
- fclose(tracker);
- fclose(melter);
- aveke /= cycles;
- avepe /= cycles;
- avetotal /=cycles;
- aveP /= cycles;
- aveT /= cycles;
- aveDs /= cycles;
-
- Ds = Ds / (cycles*dt);
-
- printf("<ke>\t<u>\t<e>\tD\t<P>\t<T>\t\n");
- printf("%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t\n",aveke,avepe,avetotal,Ds,aveP,aveT);
- fprintf(OUT,"<ke>\t<u>\t<e>\tD\t<P>\t<T>\t\n");
- fprintf(OUT,"%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t\n",aveke,avepe,avetotal,Ds,aveP,aveT);
-
- fclose(OUT);
-
- free(positions);
- free(velocities);
- free(force);
- free(potential);
- free(neighborlist);
- free(avevel);
- free(pix);
- free(tracer);
- free(blinker);
- codeend = clock();
- codetime = (double)(codeend - codebegin) / CLOCKS_PER_SEC;
-
- printf("Timing results\n");
- if (strcmp(vyes,"Y") == 0) {
- printf("Whole Code\tInitialization\tVelscale\tProduction\n");
- printf("%lf\t%lf\t%lf\t%lf\n",codetime,inittime,veltime,productiontime);
-
- } else if( strcmp(yes,"Y") == 0 ) {
- printf("Whole Code\tInitialization\tAndersen\tProduction\n");
- printf("%lf\t%lf\t%lf\t%lf\n",codetime,inittime,andersentime,productiontime);
- }
-
- }
-
- double random1() {
- return (double)random()/RAND_MAX;
- }
-
- double maxwell() {
-
- double x1, x2, w, y1, y2;
- do {
- x1 = 2.0 * random1() - 1.0;
- x2 = 2.0 * random1() - 1.0;
- w = x1 * x1 + x2 * x2;
- } while ( w >= 1.0 );
- w = sqrt( (-2.0 * log10( w ) ) / w );
- y1 = x1 * w;
- y2 = x2 * w;
- return y2;
-
- }
-
- double gauss(double std, double mean ) {
-
- double rand;
- rand = random1();
-
- rand = mean + std*rand;
- return rand;
- }
-
- void velscaler(double *velocity, double T, int n) {
-
- int i,j;
- double square_vel[nDim], velscale;
- for (i = 0; i<nDim; i++) {
- square_vel[i] = 0.0;
- }
-
- for (i=0; i<n; i++) {
- for (j=0;j<nDim;j++) {
- square_vel[j] += *(velocity + j*n+ i) * *(velocity +j*n + i);
- }
- }
- velscale = sqrt(3*T/((square_vel[0]+square_vel[1]+square_vel[2])/n));
- for (i=0;i<n;i++) {
- for (j=0;j<nDim;j++) {
- *(velocity + j*n + i) *= velscale;
- }
- }
-
- }
-
- void initialization(double *positions, double *velocities, int n, double L, double T) {
- int N, i, j, k, flag;
- double del, ndouble, per_dimension, *sum_velocity, *squared_velocity, velscale, rcutoff;
- double r, tester;
- per_dimension = pow(n,1/3.0);
- rcutoff = 0.212;
- del = L/per_dimension;
-
- N = 0;
- flag = 0;
- sum_velocity = malloc(3*sizeof(double));
- squared_velocity = malloc(3*sizeof(double));
- for(i=0;i<nDim;i++) {
- *(sum_velocity + i) = 0.0;
- *(squared_velocity + i) = 0.0;
- }
-
- for (i=0;i< per_dimension; i++) {
- for(j=0;j< per_dimension; j++) {
- for(k=0; k< per_dimension;k++) {
- *(positions + 0*n + N) = i * del;
- *(positions + 1*n + N) = j * del;
- *(positions + 2*n + N) = k * del;
- N++;
- }
- }
- }
-
-
- for(i=0; i<n; i++) {
- *(velocities + i) = maxwell();
- *(velocities + 1*n + i) = maxwell();
- *(velocities + 2*n + i) = maxwell();
-
- *(sum_velocity) += *(velocities + i)/n;
- *(sum_velocity + 1) += *(velocities + 1*n + i)/n;
- *(sum_velocity + 2) += *(velocities + 2*n + i)/n;
- }
-
- for (i=0;i<n;i++) {
- *(velocities + i) -= *(sum_velocity);
- *(velocities + 1*n + i) -= *(sum_velocity + 1);
- *(velocities + 2*n + i) -= *(sum_velocity + 2);
- }
- velscaler(velocities,T,n);
- }
-
- int neighborhood(double *position, int *celllist, int n, double L, double rcut) {
-
- int i,j,k,xcell,ycell,zcell, Nmax;
- double x,y,z, halfL, distance[nDim], r;
- Nmax = 0;
- for (i = 0; i<n; i++) {
- for(j=i+1;j<n; j++) {
- r = 0.0;
- if(i == j) { break;}
- distance[0] = *(position + i) - *(position + j);
- distance[1] = *(position + n + i) - *(position + n + j);
- distance[2] = *(position + 2*n + i) - *(position + 2*n + j);
-
- halfL = L/2.0;
- for (k=0;k<nDim;k++) {
- if (distance[k] > halfL) {
- distance[k] = distance[k] - L;
- } else if( distance[k] < -halfL ) {
- distance[k] = distance[k] + L;
- }
- r = r + distance[k]*distance[k];
- }
- r = sqrt(r);
-
-
- if (r <= rcut) {
- *(celllist + Nmax*2 + 1) = i;
- *(celllist + Nmax*2 + 2) = j;
- Nmax = Nmax + 1;
- }
- }
- }
- if (Nmax == 0 ) {
- printf("No near atoms\n");
- return 0;
- }
- return Nmax;
- }
-
- void LJ_Forces( double *force, double *potential, double *position, int n, int Nmax, int *celllist, double L, double rcut, double rmax, double *px){
- int i, j, k, x, y, z, num;
- double distance[nDim], halfL,ir6, U, F, r, r6, ir, r2, numerator, den, rmax2, rcut2, virial, tester;
- double ucut;
- ucut = 4*(1/(rcut*rcut*rcut*rcut*rcut*rcut))*((1/(rcut*rcut*rcut*rcut*rcut*rcut)) - 1);
- virial = 0.0;
- memset(potential,0.0,n*sizeof(double));
- memset(force,0.0,nDim*n*sizeof(double));
- memset(px,0.0,nDim*sizeof(double));
-
- virial = 0.0;
- halfL = L/2.0;
- for ( num = 0; num<Nmax; num++) {
- r = 0.0;
- i = *(celllist + num*2 + 1);
- j = *(celllist + num*2 + 2);
- if( i != j) {
- distance[0] = *(position + i) - *(position + j);
- distance[1] = *(position + n + i) - *(position + n + j);
- distance[2] = *(position + 2*n + i) - *(position + 2*n + j);
- for (k=0;k<nDim;k++) {
- if (distance[k] > halfL) {
- distance[k] = distance[k] - L;
- }else if( distance[k] < -halfL ) {
- distance[k] = distance[k] + L;
- }
- }
- r2 = distance[0]*distance[0]+distance[1]*distance[1]+distance[2]*distance[2];
- r = sqrt(r2);
-
- if (r <= rcut) {
- ir = 1.0/r;
- r6 = r2*r2*r2;
- ir6 = 1.0/r6;
- U = 4.0*ir6*(ir6-1.);
- F = 48.0*(ir6*ir6-0.5*ir6);
-
- *(potential + i) += U;
- for (k =0; k<nDim; k++) {
- *(force + k*n + i) += F*distance[k]*ir*ir;
- *(force + k*n + j) -= F*distance[k]*ir*ir;
- }
- virial += F;
-
- }else if(r>rcut && r< rmax) {
- r6 = r*r*r*r*r*r;
- r2 = r*r;
- rmax2 = rmax*rmax;
- rcut2 = rcut*rcut;
- numerator = 24.0*(rmax*rmax-r2)*(rmax2*rmax2*(r6-2.0)-rmax2*(r6-2.0)*(3.0*rcut2-r2)+rcut2*r2*(r6-4.0)+2.0*r2*r2);
- den = r6*r6*r*(rmax2-rcut2)*(rmax2-rcut2)*(rmax2-rcut2);
- ir6 = 1./r6;
- U = 4.0*ir6*(ir6-1.0)*(rmax*rmax-r*r)*(rmax*rmax-r*r)*(rmax*rmax+2.0*r*r-3.0*rcut*rcut)/((rmax*rmax-rcut*rcut)*(rmax*rmax-rcut*rcut)*(rmax*rmax-rcut*rcut));
- *(potential + i) += U;
- F = -numerator/den;
- for (k =0; k<nDim; k++) {
- *(force + k*n + i) += F*distance[k]/r;
- *(force + k*n + j) -= F*distance[k]/r;
- }
- }
-
- }
- }
- *(px) = virial;
- }
-
- void andersen(int switch1, int n, double *force, double *velocity, double *positions,double *tracer, double dt, double T, double L, int *blinker ) {
-
- int i,j;
- double Temp, rand;
- double nu = 0.2;
- if (switch1 == 1) {
- for (i=0;i<n;i++) {
- for (j = 0; j<nDim; j++) {
- *(positions + j*n + i ) += *(velocity +j*n + i)*dt + 0.5 * *(force +j*n + i)*dt*dt;
- *(velocity + j*n + i ) += 0.5 * (*(force + j*n + i)) * dt;
- *(tracer + j*n + i) += *(velocity +j*n + i)*dt + 0.5 * *(force +j*n + i)*dt*dt;
- if( *(positions + j*n + i) < 0.0) {
- *(positions + j*n + i) = *(positions + j*n + i) + L;
- *(blinker + j*n + i) -= 1;
- }
- if( *(positions + j*n + i) > L ) {
- *(positions + j*n + i) = *(positions + j*n + i) - L;
- *(blinker + j*n + i) += 1;
- }
- }
- }
- } else if(switch1 == 3 || switch1 == 2 ) {
- Temp = 0.0;
- for (i = 0;i<n;i++) {
- for (j=0;j<nDim;j++) {
- *(velocity + j*n + i ) = *(velocity + j*n + i ) + 0.5 * *(force + j*n + i) * dt;
- }
- }
- if(switch1 == 3) {
- for(i=0;i<n;i++) {
- for(j=0;j<nDim;j++) {
- rand = random1();
- if(rand < nu*dt) {
-
- *(velocity + j*n + i) = gauss(sqrt(T),0);
- }
- }
- }
- }
- }
- }
-
- void properties(double *position, double *tracer, double *velocities, double *forces, double *potential, int n, double *U, double *KE, double *energy, double *avevel, double *Temp, double *px, double *pressure, double v, double rcut, double rho, double L, double *Ds, double timecount) {
- int i,j,k;
- double fx, fy, fz, radius, radiust, radiusz, virial;
- double distance[3], F, radius6, radius12, ucor, pcor, rcut9, rcut3, halfL;
- rcut3 = rcut*rcut*rcut;
- rcut9 = rcut3*rcut3*rcut3;
- ucor = 8.0*3.1415926*rho*(1.0/(9.0*rcut9)-1.0/(3.0*rcut3));
- pcor = 16.0*3.1415926*rho*(2.0/(9.0*rcut9)-1.0/(3.0*rcut3));
- halfL = L/2.0;
- *U = 0.0;
- *KE = 0.0;
- *(avevel) = 0.0;
- *(avevel + 1 ) = 0.0;
- *(avevel + 2) = 0.0;
- radiust = 0.0;
- *Ds = 0.0;
- for (j=0;j<n;j++) {
- *(avevel) += *(velocities + j);
- *(avevel + 1 ) += *(velocities + n + j);
- *(avevel + 2) += *(velocities + 2*n + j);
- *U += *(potential + j);
- *Ds += *(tracer + j) * *(tracer + j) + *(tracer + n + j) * *(tracer + n +j) + *(tracer + 2*n + j) * *(tracer + 2*n +j);
-
- }
- *Ds = *Ds / (2*nDim*n) ;
-
- *(avevel) /= n;
- *(avevel + 1 ) /= n;
- *(avevel + 2) /= n;
-
- for(j = 0; j<n; j++) {
- *KE += (*(velocities + j) - *(avevel)) * (*(velocities + j) - *(avevel)) + (*(velocities + n + j)- *(avevel + 1)) * (*(velocities + n + j)- *(avevel + 1)) + (*(velocities + 2*n + j)-*(avevel + 2)) * (*(velocities + 2*n + j)-*(avevel + 2));
- }
- *U /= n;
- *U += ucor;
- *KE = *KE/(2.0 * n);
- *Temp = (2.0/3.0) * *KE ;
- *energy = *KE + *U;
- *pressure = 0.0;
- *pressure = *px / 3.0;
- *pressure += n * *Temp;
- *pressure /= v;
- *pressure += pcor;
- }
-
- void position_printer(FILE * fp, double * positions, int n, int *blinker, double L, int flag) {
- int i;
- double length;
- length = sigma*10.0/(1.0e-9);
- fprintf(fp,"%d\n\n",n);
- if (flag == 1) {
- for (i=0;i<n;i++) {
- fprintf(fp,"Ar %lf %lf %lf\n", *(positions + i)*length + *(blinker + i)*L*length, *(positions + n + i)*length + *(blinker + n + i)*L*length, *(positions + 2*n + i)*length + *(blinker + 2*n + i)*L*length);
- }
- } else if(flag == 0) {
- for (i=0;i<n;i++) {
- fprintf(fp,"Ar %lf %lf %lf\n", *(positions + i)*length, *(positions + n + i)*length, *(positions + 2*n + i)*length);
- }
- }
- }
-
- void velocity_printer(FILE *fp, double * velocity, int n ) {
- int i;
- double Vx, Vy, Vz;
- double V;
- for(i=0;i<n;i++) {
- Vx = *(velocity + i) * *(velocity + i);
- Vy = *(velocity + n + i) * *(velocity + n + i);
- Vz = *(velocity + 2*n + i) * *(velocity + 2*n + i);
- V = sqrt(Vx + Vy + Vz);
- fprintf(fp,"%lf\n",V);
- }
- }