void mbChargeLattice::allocLattice() { deallocLattice(); cubeCount = xDim*yDim*zDim; pointCount = (xDim + 1)*(yDim + 1)*(zDim + 1); edgeCount = (cubeCount * 3) + ((2 * xDim * yDim) + (2 * xDim * zDim) + (2 * yDim * zDim)) + xDim + yDim + zDim; //Ideal Edge Count edgeCount += ((xDim * yDim) + (yDim * zDim) + (zDim * xDim)) * 2; //Haven't combined the edges of the 0 index borders chargeLattice = new float[xDim*yDim*zDim]; latticeCubes = new mbLatticeCube[cubeCount]; latticeEdges = new mbLatticeEdge[edgeCount]; latticePoints = new mbLatticePoint[pointCount]; initializeLattice(); };
int main(int argc, char **argv) { //Initialization: Read in particle locations. Also add function for random init, latttice init, and lattice init with perturb. Add velocities! FILE* input_file; if ((input_file = fopen(argv[1],"r"))==NULL) { printf("Error opening %s\n",argv[1]); return 1; } //open file -> change to read initial configuration from LAMMPS or XYZ files fscanf(input_file,"%d %*[^\n]", &N); //number of particles fscanf(input_file,"%d %*[^\n]", &init_type); //initialization type fscanf(input_file,"%lf %*[^\n]", &L); //length of box - box extends in 3 dim from -L/2 to +L/2 fscanf(input_file,"%d %*[^\n]", &ntypes); //number of particle types fscanf(input_file,"%lf %*[^\n]", ×tep); //delta t fscanf(input_file,"%d %*[^\n]", &nsteps); //number of timesteps fscanf(input_file,"%lf %*[^\n]", &epsilon_scale); //epsilon_scale fscanf(input_file,"%lf %*[^\n]", &T_in); //initial tempertaure L2 = L/2; double* epsilontemp; double* sigmatemp; if((p = (struct atom*)malloc(N*sizeof(struct atom)))==NULL) { printf("Could not allocate array of particles\n"); return 1; } if((npertype = (int*)malloc(ntypes*sizeof(int)))==NULL) { printf("Could not allocate array of type counts\n"); return 1; } if((epsilontemp = (double*)malloc(ntypes*sizeof(double)))==NULL) { printf("Could not allocate array of epsilons\n"); return 1; } if((epsilon = (double**)malloc(ntypes*sizeof(double*)))==NULL) { printf("Could not allocate array of epsilons\n"); return 1; } if((sigmatemp = (double*)malloc(ntypes*sizeof(double)))==NULL) { printf("Could not allocate array of sigmas\n"); return 1; } if((sigma2 = (double**)malloc(ntypes*sizeof(double*)))==NULL) { printf("Could not allocate array of sigmas\n"); return 1; } int i=0; for (i=0; i<ntypes; i++) { if((epsilon[i] = (double*)malloc(ntypes*sizeof(double)))==NULL) { printf("Could not allocate array of epsilons\n"); return 1; } if((sigma2[i] = (double*)malloc(ntypes*sizeof(double)))==NULL) { printf("Could not allocate array of sigmas\n"); return 1; } } if((m = (double*)malloc(ntypes*sizeof(double)))==NULL) { printf("Could not allocate array of masses\n"); return 1; } int j,k=0; double mave = 0.0;//average mass for (i=0; i<ntypes; i++) { fscanf(input_file,"%d %*[^\n]", &npertype[i]); fscanf(input_file,"%lf %*[^\n]", &sigmatemp[i]); fscanf(input_file,"%lf %*[^\n]", &epsilontemp[i]); fscanf(input_file,"%lf %*[^\n]", &m[i]); mave+=npertype[i]*m[i]; for(j=0; j<npertype[i]; j++) { p[k].type = i; k++; } } for (i=0; i<ntypes; i++) { for (j=0; j<ntypes; j++) { sigma2[i][j] = pow((sigmatemp[i]+sigmatemp[j])/2.0,2); epsilon[i][j] = (sqrt(epsilontemp[i]*epsilontemp[j])); } } free(sigmatemp); free(epsilontemp); mave = mave/N; printf("Initializing positions..."); if (init_type == 0 ) { //Test on one particle - put it in the middle of the box. for(i=0; i<N; i++) { p[i].x=0.0; p[i].y=0.0; p[i].z=0.0; } } if(init_type == 1) { //Complete this for LAMMPS - style frame printf("Initialization type not yet implemented"); return 1; FILE* input_coords_file; if ((input_coords_file = fopen(argv[1],"r"))==NULL) { printf("Error opening %s\n",argv[1]); return 1; } fclose(input_coords_file); } if(init_type == 2) { //Random initializeRand(N,L); } if(init_type == 3) { //Lattice initializeLattice(N,L); } if(init_type == 4) { //LAttice plus perturb. printf("Initialization type not yet implemented"); return 1; } //Initialize forces for (i=0; i<N; i++) { p[i].fx = 0.0; p[i].fy = 0.0; p[i].fz = 0.0; } printf("Initializing velocities..."); //Randomly assign velocities from continous distribution [-vrange,+vrange], compute total velocity and correct momentum. //Calculate vrange from input T assuming uniform distribution T = T_in/epsilon_scale; //some base epsilon, all epsilons in epsilon array are multiples of this epsilon_scale. double vrange = sqrt(T*2.0/mave); //Vrange is range of the uniform distribution with rms v^2, solve using KE = 3NT/2 = 3Nmvrange^2/4 from v_ave = (2vrange)^2/12. Using averge mass: is this correct? double mass, vx, vy, vz, sumpx, sumpy, sumpz; sumpx = 0.0; sumpy = 0.0; sumpz = 0.0; for (i=0; i<N; i++) { mass = m[(p[i].type)]; vx = (Random()*vrange*2.0) - vrange; p[i].xold = p[i].x-(vx*timestep); sumpx+=vx*mass; vy = (Random()*vrange*2.0) - vrange; p[i].yold = p[i].y-(vy*timestep); sumpy+=vy*mass; vz = (Random()*vrange*2.0) - vrange; p[i].zold = p[i].z-(vz*timestep); sumpz+=vz*mass; } //The following obviously does not work for 1 particle test simulation or it will not move. Rather, it does work and the particle therefore does not move. if (fabs(sumpx)>ptol) { //If total momentum is not zero, correct all velocities by v_tot/N sumpx = sumpx/N; for(i=0; i<N; i++) { vx = ((p[i].x - p[i].xold)/timestep) - sumpx; p[i].xold = p[i].x-(vx*timestep); } } if (fabs(sumpy)>ptol) { sumpy = sumpy/N; for(i=0; i<N; i++) { vy = ((p[i].y - p[i].yold)/timestep) - sumpy; p[i].yold = p[i].y-(vy*timestep); } } if (fabs(sumpz)>ptol) { sumpz = sumpz/N; for(i=0; i<N; i++) { vz = ((p[i].z - p[i].zold)/timestep) - sumpz; p[i].zold = p[i].z-(vz*timestep); } } FILE* xyz_file; if ((xyz_file = fopen(argv[2],"w"))==NULL) { printf("Error opening xyz file\n"); return 1; } fprintf(xyz_file, "%d\n Initial configuration\n", N); for(i=0; i<N; i++) { fprintf(xyz_file,"%5d %13lf %13lf %13lf\n", p[i].type, p[i].x, p[i].y, p[i].z); } //Contents of main loop printf("Beginning simulation..."); int iter; for (iter = 0; iter<nsteps; iter++) { //run for desired number of time steps printf("%d\t",iter); //Force Computation (function), using minimum image, with cutoff rc(?). Compute P in here, but separate function. Compute U in here. Put in a function. double pix, piy, piz, pifx, pify, pifz, xij, yij, zij, rij, rij2, epsilonij, sr2, sr6, sr12, fij, factor, PE=0.0; int ptype; for (i=0; i<N; i++) { pix = p[i].x; piy = p[i].y; piz = p[i].z; pifx = 0.0; //add to force for particle i pify = 0.0; pifz = 0.0; ptype = p[i].type; for (j=i+1 ; j<N; j++) { xij = pix - p[j].x; if (xij>L2) { //Minimum image condition -> Need to use absolute value here! But also maintain sign of vector xij = xij - L; } else if (xij<-L2) { xij = xij + L; } yij = piy - p[j].y; if (yij>L2) { yij = L-yij; } else if (yij<-L2) { yij = yij + L; } zij = piz - p[j].z; if (zij>L2) { zij = L-zij; } else if (zij<-L2) { zij = zij + L; } rij2 = (xij*xij)+(yij*yij)+(zij*zij); rij = sqrt(rij2); epsilonij = epsilon[(p[i].type)][(p[j].type)]; sr2 = sigma2[(p[i].type)][(p[j].type)]/rij2; sr6 = sr2*sr2*sr2; sr12 = sr6*sr6; fij = (-24.0*epsilonij/rij2)*(2*sr12-sr6); //magnitude of force PE = PE + epsilonij*(sr12 - sr6); //add potential to total potential factor = fij/rij; xij = factor*xij; //get vectors yij = factor*yij; zij = factor*zij; pifx+=xij; //add to force for particle i pify+=yij; pifz+=zij; p[j].fx -= pifx; //add negative force to force on jth particle since fij = -fji -> DO need to "double-count" forces p[j].fy -= pify; p[j].fz -= pifz; } p[i].fx += pifx; p[i].fy += pify; p[i].fz += pifz; } PE = 4.0*PE; //Integration: Verlet integrator. Compute KE in here and T in here. double xnew, ynew, znew, mass, vx, vy, vz, KE, KEsumm=0.0, sumvsq; double dtsq = timestep*timestep; double dt2 = 2*timestep; sumpx = 0.0; sumpy = 0.0; sumpz = 0.0; sumvsq = 0.0; for (i=0; i<N; i++) { mass = m[(p[i].type)]; factor = dtsq/mass; xnew = 2.0*p[i].x - p[i].xold + factor*p[i].fx; ynew = 2.0*p[i].y - p[i].yold + factor*p[i].fy; znew = 2.0*p[i].z - p[i].zold + factor*p[i].fz; vx = (xnew - p[i].xold)/dt2; vy = (ynew - p[i].yold)/dt2; vz = (znew - p[i].zold)/dt2; sumvsq = sumvsq + mass*(vx*vx + vy*vy + vz*vz); sumpx+=vx*mass; sumpy+=vy*mass; sumpz+=vz*mass; //PBC while (xnew < -L2) { xnew = xnew + L; } while (xnew>L2) { xnew = xnew - L; } while (ynew < -L2) { ynew = ynew + L; } while (ynew>L2) { ynew = ynew - L; } while (znew < -L2) { znew = znew + L; } while (znew>L2) { znew = znew - L; } p[i].xold = p[i].x; p[i].yold = p[i].y; p[i].zold = p[i].z; p[i].x = xnew; p[i].y = ynew; p[i].z = znew; } //Compute KE and T KE = 0.5*sumvsq; //reduced energy = KE/epsilon KEsumm += KE; //To get ensemble average? T = 2.0*KE/(3.0*N); //reduced temperature = kbT/epsilon //Output (positions for frame) fprintf(xyz_file, "%5d\n%5d\n", N, iter); for(i=0; i<N; i++) { fprintf(xyz_file,"%5d %13lf %13lf %13lf\n", p[i].type, p[i].x, p[i].y, p[i].z); } // fprintf(output, "%5d %13lf %13lf %13lf %13lf", iter, KE_out, PE_out, T_out, pressure_out); } printf("\nWrapping up..."); fclose(xyz_file); //Final output here free(p); free(epsilon); free(sigma2); free(m); return 0; }