Пример #1
0
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();
};
Пример #2
0
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]", &timestep); //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;
}