void force_LJ(mdsys_t *sys) { double rsq,ffac; double rx,ry,rz; double b = 0.5*sys->box; double s = sys->sigma*sys->sigma; double p = s*s*s; double csq = sys->rcut*sys->rcut; int i,j; int natoms=sys->natoms; /* zero energy and forces */ sys->epot=0.0; azzero(sys->fx,natoms); azzero(sys->fy,natoms); azzero(sys->fz,natoms); for(i=0; i < natoms-1; ++i) { for(j=i+1; j < natoms; ++j) { /* particles have no interactions with themselves */ if (i==j) continue; /* get distance between particle i and j */ rx=pbc(sys->rx[i] - sys->rx[j], b); ry=pbc(sys->ry[i] - sys->ry[j], b); rz=pbc(sys->rz[i] - sys->rz[j], b); rsq = rx*rx + ry*ry + rz*rz; /* compute force and energy if within cutoff */ if (rsq < csq) { double rsqinv = 1/rsq; double r6 = rsqinv*rsqinv*rsqinv; double pr = p*r6; double p6 = 4.0*sys->epsilon*pr; double p12 = p6*pr; ffac = rsqinv*(12*p12-6*p6); sys->epot += 0.5*(p12-p6); sys->fx[i] += rx*ffac; sys->fy[i] += ry*ffac; sys->fz[i] += rz*ffac; sys->fx[j] -= rx*ffac; sys->fy[j] -= ry*ffac; sys->fz[j] -= rz*ffac; } } } }
void force_morse(mdsys_t *sys) { double rsq,ffac; double rx,ry,rz; double b = 0.5*sys->box; double s = sys->sigma*sys->sigma; double p = s*s*s; double csq = sys->rcut*sys->rcut; int i,j; int natoms=sys->natoms; /* zero energy and forces */ sys->epot=0.0; azzero(sys->fx,natoms); azzero(sys->fy,natoms); azzero(sys->fz,natoms); for(i=0; i < natoms-1; ++i) { for(j=i+1; j < natoms; ++j) { /* particles have no interactions with themselves */ if (i==j) continue; /* get distance between particle i and j */ rx=pbc(sys->rx[i] - sys->rx[j], b); ry=pbc(sys->ry[i] - sys->ry[j], b); rz=pbc(sys->rz[i] - sys->rz[j], b); rsq = rx*rx + ry*ry + rz*rz; rs = sqrt(rsqi); rsq = rx*rx + ry*ry + rz*rz; /* compute force and energy if within cutoff */ if (rsq < csq) { esp = exp((-1)*sys->a*(rs-sys->rzero)); espq = exp((-1)*sys->a*(rs-sys->rzero)*(rs-sys->rzero)); ffac = 2*sys->De * (1-esp)*sys->a*esp; sys->epot += sys->De*(1-espq) sys->fx[i] += rx*ffac; sys->fy[i] += ry*ffac; sys->fz[i] += rz*ffac; sys->fx[j] -= rx*ffac; sys->fy[j] -= ry*ffac; sys->fz[j] -= rz*ffac; } } } }
void MyMD::readRestart() { FILE *fp=fopen(restfile,"r"); if(fp) { int natoms=atoms->GetNAtoms(); double index1, index2, index3; index1=index2=index3=0; for(int i=0; i<natoms; ++i) { fscanf(fp,"%lf%lf%lf", &index1, &index2, &index3); atoms->SetPosition(i, index1); atoms->SetPosition(i+natoms, index2); atoms->SetPosition(i+2*natoms, index3); } for(int i=0; i<natoms; ++i) { fscanf(fp,"%lf%lf%lf", &index1, &index2, &index3); atoms->SetVelocity(i, index1); atoms->SetVelocity(i+natoms, index2); atoms->SetVelocity(i+2*natoms, index3); } fclose(fp); azzero(atoms->GetForce(), 3*nthreads*natoms); } else { perror("cannot read restart file"); exit(1); } }
/* compute forces */ void force(mdsys_t *sys) { double r,ffac; double rx,ry,rz; int i,j; /* zero energy and forces */ sys->epot=0.0; azzero(sys->fx,sys->natoms); azzero(sys->fy,sys->natoms); azzero(sys->fz,sys->natoms); for(i=0; i < (sys->natoms); ++i) { for(j=0; j < (sys->natoms); ++j) { /* particles have no interactions with themselves */ if (i==j) continue; /* get distance between particle i and j */ rx=pbc(sys->rx[i] - sys->rx[j], 0.5*sys->box); ry=pbc(sys->ry[i] - sys->ry[j], 0.5*sys->box); rz=pbc(sys->rz[i] - sys->rz[j], 0.5*sys->box); r = sqrt(rx*rx + ry*ry + rz*rz); /* compute force and energy if within cutoff */ if (r < sys->rcut) { ffac = -4.0*sys->epsilon*(-12.0*pow(sys->sigma/r,12.0)/r +6*pow(sys->sigma/r,6.0)/r); sys->epot += 0.5*4.0*sys->epsilon*(pow(sys->sigma/r,12.0) -pow(sys->sigma/r,6.0)); sys->fx[i] += rx/r*ffac; sys->fy[i] += ry/r*ffac; sys->fz[i] += rz/r*ffac; } } } }
/* compute forces */ void force(mdsys_t *sys) { double r_c2 = sys->rcut * sys->rcut; double c1, c2, c3, c4, sig6; double epot; int i; /* zero energy and forces */ epot=0.0; azzero(sys->fx,sys->natoms); azzero(sys->fy,sys->natoms); azzero(sys->fz,sys->natoms); /* Precalculate some of the constants used in the potential */ sig6 = (sys->sigma)*(sys->sigma)*(sys->sigma) * (sys->sigma)*(sys->sigma)*(sys->sigma); c1 = -24.0 * sys->epsilon * sig6; c2 = 48.0 * sys->epsilon * sig6 * sig6; c3 = -4.0 * sys->epsilon * sig6; // Leading 4.0 includes factor 2 c4 = 4.0 * sys->epsilon * sig6 * sig6; // for using Newton's 3rd law (Epot) #ifdef _OPENMP #pragma omp parallel for private(i) reduction(+:epot) #endif for(i=0; i < (sys->natoms); ++i) { int j; double r6; double rxi, ryi, rzi; double fx, fy, fz; fx = fy = fz = 0.0; rxi = sys->rx[i]; ryi = sys->ry[i]; rzi = sys->rz[i]; for(j=i+1; j < (sys->natoms); ++j) { double rx, ry, rz; double r2, ffac; /* get distance between particle i and j */ rx = pbc(rxi - sys->rx[j], 0.5*sys->box); ry = pbc(ryi - sys->ry[j], 0.5*sys->box); rz = pbc(rzi - sys->rz[j], 0.5*sys->box); r2 = rx*rx + ry*ry + rz*rz; /* compute force and energy if within cutoff */ if (r2 < r_c2) { r6 = r2*r2*r2; ffac = (c2 + c1*r6) / (r6*r6*r2); epot += (c4 + c3*r6) / (r6*r6); /* #ifdef _OPENMP #pragma omp atomic #endif sys->fx[i] += rx*ffac; #ifdef _OPENMP #pragma omp atomic #endif sys->fy[i] += ry*ffac; #ifdef _OPENMP #pragma omp atomic #endif sys->fz[i] += rz*ffac; */ fx += rx*ffac; fy += ry*ffac; fz += rz*ffac; #ifdef _OPENMP #pragma omp atomic #endif sys->fx[j] -= rx*ffac; #ifdef _OPENMP #pragma omp atomic #endif sys->fy[j] -= ry*ffac; #ifdef _OPENMP #pragma omp atomic #endif sys->fz[j] -= rz*ffac; } } /* end loop j */ #ifdef _OPENMP #pragma omp atomic #endif sys->fx[i] += fx; #ifdef _OPENMP #pragma omp atomic #endif sys->fy[i] += fy; #ifdef _OPENMP #pragma omp atomic #endif sys->fz[i] += fz; } /* end loop i */ sys->epot = epot; }
/* main */ int main(int argc, char **argv) { omp_set_num_threads(MY_NUM_THREADS); clock_t start,end; //timing variables double time_spent; int nprint, i; char restfile[BLEN], trajfile[BLEN], ergfile[BLEN], line[BLEN]; FILE *fp,*traj,*erg; mdsys_t sys; /* read input file */ if(get_a_line(stdin,line)) return 1; sys.natoms=atoi(line); if(get_a_line(stdin,line)) return 1; sys.mass=atof(line); if(get_a_line(stdin,line)) return 1; sys.epsilon=atof(line); if(get_a_line(stdin,line)) return 1; sys.sigma=atof(line); if(get_a_line(stdin,line)) return 1; sys.rcut=atof(line); if(get_a_line(stdin,line)) return 1; sys.box=atof(line); if(get_a_line(stdin,restfile)) return 1; if(get_a_line(stdin,trajfile)) return 1; if(get_a_line(stdin,ergfile)) return 1; if(get_a_line(stdin,line)) return 1; sys.nsteps=atoi(line); if(get_a_line(stdin,line)) return 1; sys.dt=atof(line); if(get_a_line(stdin,line)) return 1; nprint=atoi(line); /* allocate memory */ sys.rx=(double *)malloc(sys.natoms*sizeof(double)); sys.ry=(double *)malloc(sys.natoms*sizeof(double)); sys.rz=(double *)malloc(sys.natoms*sizeof(double)); sys.vx=(double *)malloc(sys.natoms*sizeof(double)); sys.vy=(double *)malloc(sys.natoms*sizeof(double)); sys.vz=(double *)malloc(sys.natoms*sizeof(double)); sys.fx=(double *)malloc(sys.natoms*sizeof(double)); sys.fy=(double *)malloc(sys.natoms*sizeof(double)); sys.fz=(double *)malloc(sys.natoms*sizeof(double)); /* read restart */ fp=fopen(restfile,"r"); if(fp) { for (i=0; i<sys.natoms; ++i) { fscanf(fp,"%lf%lf%lf",sys.rx+i, sys.ry+i, sys.rz+i); } for (i=0; i<sys.natoms; ++i) { fscanf(fp,"%lf%lf%lf",sys.vx+i, sys.vy+i, sys.vz+i); } fclose(fp); azzero(sys.fx, sys.natoms); azzero(sys.fy, sys.natoms); azzero(sys.fz, sys.natoms); } else { perror("cannot read restart file"); return 3; } /* initialize forces and energies.*/ sys.nfi=0; force(&sys); ekin(&sys); erg=fopen(ergfile,"w"); traj=fopen(trajfile,"w"); printf("Starting simulation with %d atoms for %d steps.\n",sys.natoms, sys.nsteps); printf(" NFI TEMP EKIN EPOT ETOT\n"); output(&sys, erg, traj); //Start timing start = clock(); /**************************************************/ /* main MD loop */ for(sys.nfi=1; sys.nfi <= sys.nsteps; ++sys.nfi) { /* write output, if requested */ if ((sys.nfi % nprint) == 0) output(&sys, erg, traj); /* propagate system and recompute energies */ velverlet1(&sys); //Velocity verlet Part 1 /* compute forces and potential energy */ force(&sys); velverlet2(&sys); //Velocity verlet Part 2 ekin(&sys); } /**************************************************/ end = clock(); //end timing time_spent = (double) (end - start) / CLOCKS_PER_SEC; /* clean up: close files, free memory */ printf("Simulation Done.\n"); printf("Timing: %f Seconds.\n", time_spent); fclose(erg); fclose(traj); free(sys.rx); free(sys.ry); free(sys.rz); free(sys.vx); free(sys.vy); free(sys.vz); free(sys.fx); free(sys.fy); free(sys.fz); return 0; }
/* compute LJ forces */ void force_LJ(mdsys_t *sys) { double pot; double b = 0.5*sys->box; double s = sys->sigma*sys->sigma; double p = s*s*s; double csq = sys->rcut*sys->rcut; int i; int natoms=sys->natoms; /* zero energy and forces */ pot=0.0; azzero(sys->fx,natoms); azzero(sys->fy,natoms); azzero(sys->fz,natoms); #pragma omp parallel for default(shared) private(i) reduction(+:pot) for(i = 0; i < (natoms - 1); ++i) { /* private versions of sys->rx[i] */ int j; double rxi,ryi,rzi; rxi = sys->rx[i]; ryi = sys->ry[i]; rzi = sys->rz[i]; for(j = (1 + i); j < natoms; ++j) { double rx,ry,rz,rsq; /* particles have no interactions with themselves */ if (i==j) continue; /* get distance between particle i and j */ rx=pbc(rxi - sys->rx[j], b); ry=pbc(ryi - sys->ry[j], b); rz=pbc(rzi - sys->rz[j], b); rsq = rx*rx + ry*ry + rz*rz; /* compute force and energy if within cutoff */ if (rsq < csq) { double rsqinv = 1/rsq; double r6 = rsqinv*rsqinv*rsqinv; double pr = p*r6; double p6 = 4.0*sys->epsilon*pr; double p12 = p6*pr; double ffac; ffac = rsqinv*(12*p12-6*p6); pot += 0.5*(p12-p6); #pragma omp atomic sys->fx[i] += rx*ffac; #pragma omp atomic sys->fy[i] += ry*ffac; #pragma omp atomic sys->fz[i] += rz*ffac; #pragma omp atomic sys->fx[j] -= rx*ffac; #pragma omp atomic sys->fy[j] -= ry*ffac; #pragma omp atomic sys->fz[j] -= rz*ffac; } } } sys->epot = pot; }
/* compute MORSE forces */ void force_morse(mdsys_t *sys) { double pot; double b = 0.5*sys->box; double s = sys->sigma*sys->sigma; double p = s*s*s; double csq = sys->rcut*sys->rcut; int i; int natoms=sys->natoms; /* zero energy and forces */ pot=0.0; azzero(sys->fx,natoms); azzero(sys->fy,natoms); azzero(sys->fz,natoms); #pragma omp parallel for default(shared) private(i) reduction(+:pot) for(i = 0; i < (natoms - 1); ++i) { /* private versions of sys->rx[i] */ int j; double rxi,ryi,rzi; rxi = sys->rx[i]; ryi = sys->ry[i]; rzi = sys->rz[i]; for(j = (1 + i); j < natoms; ++j) { double rx,ry,rz,rsq; /* particles have no interactions with themselves */ if (i==j) continue; /* get distance between particle i and j */ rx=pbc(rxi - sys->rx[j], b); ry=pbc(ryi - sys->ry[j], b); rz=pbc(rzi - sys->rz[j], b); rs = sqrt(rsqi); rsq = rx*rx + ry*ry + rz*rz; /* compute force and energy if within cutoff */ if (rsq < csq) { esp = exp((-1)*sys->a*(rs-sys->rzero)); espq = exp((-1)*sys->a*(rs-sys->rzero)*(rs-sys->rzero)); ffac = 2*sys->De * (1-esp)*sys->a*esp; pot += sys->De*(1-espq) sys->fx[i] += rx*ffac; #pragma omp atomic sys->fy[i] += ry*ffac; #pragma omp atomic sys->fz[i] += rz*ffac; #pragma omp atomic sys->fx[j] -= rx*ffac; #pragma omp atomic sys->fy[j] -= ry*ffac; #pragma omp atomic sys->fz[j] -= rz*ffac; } } } sys->epot = pot; }
/* main */ int main(int argc, char **argv) { int nprint, i; char restfile[BLEN], trajfile[BLEN], ergfile[BLEN], line[BLEN]; FILE *fp,*traj,*erg; mdsys_t sys; /* read input file */ if(get_me_a_line(stdin,line)) return 1; sys.natoms=atoi(line); if(get_me_a_line(stdin,line)) return 1; sys.mass=atof(line); if(get_me_a_line(stdin,line)) return 1; sys.epsilon=atof(line); if(get_me_a_line(stdin,line)) return 1; sys.sigma=atof(line); if(get_me_a_line(stdin,line)) return 1; sys.rcut=atof(line); if(get_me_a_line(stdin,line)) return 1; sys.box=atof(line); if(get_me_a_line(stdin,restfile)) return 1; if(get_me_a_line(stdin,trajfile)) return 1; if(get_me_a_line(stdin,ergfile)) return 1; if(get_me_a_line(stdin,line)) return 1; sys.nsteps=atoi(line); if(get_me_a_line(stdin,line)) return 1; sys.dt=atof(line); if(get_me_a_line(stdin,line)) return 1; nprint=atoi(line); /* allocate memory */ sys.rx=(double *)malloc(sys.natoms*sizeof(double)); sys.ry=(double *)malloc(sys.natoms*sizeof(double)); sys.rz=(double *)malloc(sys.natoms*sizeof(double)); sys.vx=(double *)malloc(sys.natoms*sizeof(double)); sys.vy=(double *)malloc(sys.natoms*sizeof(double)); sys.vz=(double *)malloc(sys.natoms*sizeof(double)); sys.fx=(double *)malloc(sys.natoms*sizeof(double)); sys.fy=(double *)malloc(sys.natoms*sizeof(double)); sys.fz=(double *)malloc(sys.natoms*sizeof(double)); /* read restart */ fp=fopen(restfile,"r"); if(fp) { for (i=0; i<sys.natoms; ++i) { fscanf(fp,"%lf%lf%lf",sys.rx+i, sys.ry+i, sys.rz+i); } for (i=0; i<sys.natoms; ++i) { fscanf(fp,"%lf%lf%lf",sys.vx+i, sys.vy+i, sys.vz+i); } fclose(fp); azzero(sys.fx, sys.natoms); azzero(sys.fy, sys.natoms); azzero(sys.fz, sys.natoms); } else { perror("cannot read restart file"); return 3; } /* initialize forces and energies.*/ sys.nfi=0; force(&sys); ekin(&sys); erg=fopen(ergfile,"w"); traj=fopen(trajfile,"w"); printf("Starting simulation with %d atoms for %d steps.\n",sys.natoms, sys.nsteps); printf(" NFI TEMP EKIN EPOT ETOT\n"); output(&sys, erg, traj); /**************************************************/ /* main MD loop */ for(sys.nfi=1; sys.nfi <= sys.nsteps; ++sys.nfi) { /* write output, if requested */ if ((sys.nfi % nprint) == 0) output(&sys, erg, traj); /* propagate system and recompute energies */ velverlet(&sys); ekin(&sys); } /**************************************************/ /* clean up: close files, free memory */ printf("Simulation Done.\n"); fclose(erg); fclose(traj); free(sys.rx); free(sys.ry); free(sys.rz); free(sys.vx); free(sys.vy); free(sys.vz); free(sys.fx); free(sys.fy); free(sys.fz); return 0; }
/* main */ int main(int argc, char **argv) { int nprint, i; char restfile[BLEN], trajfile[BLEN], ergfile[BLEN], line[BLEN]; FILE *fp,*traj,*erg; mdsys_t sys; #if defined(_OPENMP) #pragma omp parallel { if(0 == omp_get_thread_num()) { sys.nthreads=omp_get_num_threads(); printf("Running OpenMP version using %d threads\n", sys.nthreads); } } #else sys.nthreads=1; #endif /* read input file */ if(get_a_line(stdin,line)) return 1; sys.natoms=atoi(line); if(get_a_line(stdin,line)) return 1; sys.mass=atof(line); if(get_a_line(stdin,line)) return 1; sys.epsilon=atof(line); if(get_a_line(stdin,line)) return 1; sys.sigma=atof(line); if(get_a_line(stdin,line)) return 1; sys.rcut=atof(line); if(get_a_line(stdin,line)) return 1; sys.box=atof(line); if(get_a_line(stdin,restfile)) return 1; if(get_a_line(stdin,trajfile)) return 1; if(get_a_line(stdin,ergfile)) return 1; if(get_a_line(stdin,line)) return 1; sys.nsteps=atoi(line); if(get_a_line(stdin,line)) return 1; sys.dt=atof(line); if(get_a_line(stdin,line)) return 1; nprint=atoi(line); /* allocate memory */ sys.pos=(double *)malloc(3*sys.natoms*sizeof(double)); sys.vel=(double *)malloc(3*sys.natoms*sizeof(double)); sys.frc=(double *)malloc(sys.nthreads*3*sys.natoms*sizeof(double)); /* read restart */ fp=fopen(restfile,"r"); if(fp) { int natoms; natoms=sys.natoms; for (i=0; i<natoms; ++i) { fscanf(fp,"%lf%lf%lf",sys.pos+i, sys.pos+natoms+i, sys.pos+2*natoms+i); } for (i=0; i<natoms; ++i) { fscanf(fp,"%lf%lf%lf",sys.vel+i, sys.vel+natoms+i, sys.vel+2*natoms+i); } fclose(fp); azzero(sys.frc, 3*sys.nthreads*sys.natoms); } else { perror("cannot read restart file"); return 3; } /* initialize forces and energies.*/ sys.nfi=0; sys.clist=NULL; sys.plist=NULL; updcells(&sys); force(&sys); ekin(&sys); erg=fopen(ergfile,"w"); traj=fopen(trajfile,"w"); printf("Starting simulation with %d atoms for %d steps.\n",sys.natoms, sys.nsteps); printf(" NFI TEMP EKIN EPOT ETOT\n"); output(&sys, erg, traj); /**************************************************/ /* main MD loop */ for(sys.nfi=1; sys.nfi <= sys.nsteps; ++sys.nfi) { /* write output, if requested */ if ((sys.nfi % nprint) == 0) output(&sys, erg, traj); /* propagate system and recompute energies */ velverlet(&sys); ekin(&sys); /* update cell list */ if ((sys.nfi % cellfreq) == 0) updcells(&sys); } /**************************************************/ /* clean up: close files, free memory */ printf("Simulation Done.\n"); fclose(erg); fclose(traj); free(sys.pos); free(sys.vel); free(sys.frc); free_cell_list(&sys); return 0; }
/* compute forces */ static void force(mdsys_t *sys) { double epot; epot = 0.0; #if defined(_OPENMP) #pragma omp parallel reduction(+:epot) #endif { double c12,c6,boxby2,rcsq; double *fx, *fy, *fz; const double *rx, *ry, *rz; int i, tid, fromidx, toidx, natoms; /* precompute some constants */ c12 = 4.0*sys->epsilon*pow(sys->sigma,12.0); c6 = 4.0*sys->epsilon*pow(sys->sigma, 6.0); rcsq= sys->rcut * sys->rcut; boxby2 = 0.5*sys->box; natoms = sys->natoms; epot = 0.0; /* let each thread operate on a different part of the enlarged force array */ #if defined(_OPENMP) tid=omp_get_thread_num(); #else tid=0; #endif fx=sys->frc + (3*tid*natoms); azzero(fx,3*natoms); fy=sys->frc + ((3*tid+1)*natoms); fz=sys->frc + ((3*tid+2)*natoms); rx=sys->pos; ry=sys->pos + natoms; rz=sys->pos + 2*natoms; /* self interaction of atoms in cell */ for(i=0; i < sys->ncell; i += sys->nthreads) { int j; const cell_t *c1; j = i + tid; if (j >= (sys->ncell)) break; c1=sys->clist + j; for (j=0; j < c1->natoms-1; ++j) { int ii,k; double rx1, ry1, rz1; ii=c1->idxlist[j]; rx1=rx[ii]; ry1=ry[ii]; rz1=rz[ii]; for(k=j+1; k < c1->natoms; ++k) { int jj; double rx2,ry2,rz2,rsq; jj=c1->idxlist[k]; /* get distance between particle i and j */ rx2=pbc(rx1 - rx[jj], boxby2, sys->box); ry2=pbc(ry1 - ry[jj], boxby2, sys->box); rz2=pbc(rz1 - rz[jj], boxby2, sys->box); rsq = rx2*rx2 + ry2*ry2 + rz2*rz2; /* compute force and energy if within cutoff */ if (rsq < rcsq) { double r6,rinv,ffac; rinv=1.0/rsq; r6=rinv*rinv*rinv; ffac = (12.0*c12*r6 - 6.0*c6)*r6*rinv; epot += r6*(c12*r6 - c6); fx[ii] += rx2*ffac; fy[ii] += ry2*ffac; fz[ii] += rz2*ffac; fx[jj] -= rx2*ffac; fy[jj] -= ry2*ffac; fz[jj] -= rz2*ffac; } } } } /* interaction of atoms in different cells */ for(i=0; i < sys->npair; i += sys->nthreads) { int j; const cell_t *c1, *c2; j = i + tid; if (j >= (sys->npair)) break; c1=sys->clist + sys->plist[2*j]; c2=sys->clist + sys->plist[2*j+1]; for (j=0; j < c1->natoms; ++j) { int ii, k; double rx1, ry1, rz1; ii=c1->idxlist[j]; rx1=rx[ii]; ry1=ry[ii]; rz1=rz[ii]; for(k=0; k < c2->natoms; ++k) { int jj; double rx2,ry2,rz2,rsq; jj=c2->idxlist[k]; /* get distance between particle i and j */ rx2=pbc(rx1 - rx[jj], boxby2, sys->box); ry2=pbc(ry1 - ry[jj], boxby2, sys->box); rz2=pbc(rz1 - rz[jj], boxby2, sys->box); rsq = rx2*rx2 + ry2*ry2 + rz2*rz2; /* compute force and energy if within cutoff */ if (rsq < rcsq) { double r6,rinv,ffac; rinv=1.0/rsq; r6=rinv*rinv*rinv; ffac = (12.0*c12*r6 - 6.0*c6)*r6*rinv; epot += r6*(c12*r6 - c6); fx[ii] += rx2*ffac; fy[ii] += ry2*ffac; fz[ii] += rz2*ffac; fx[jj] -= rx2*ffac; fy[jj] -= ry2*ffac; fz[jj] -= rz2*ffac; } } } } /* before reducing the forces, we have to make sure that all threads are done adding to them. */ #if defined (_OPENMP) #pragma omp barrier #endif /* set equal chunks of index ranges */ i = 1 + (3*natoms / sys->nthreads); fromidx = tid * i; toidx = fromidx + i; if (toidx > 3*natoms) toidx = 3*natoms; /* reduce forces from threads with tid != 0 into the storage of the first thread. since we have threads already spawned, we do this in parallel. */ for (i=1; i < sys->nthreads; ++i) { int offs, j; offs = 3*i*natoms; for (j=fromidx; j < toidx; ++j) { sys->frc[j] += sys->frc[offs+j]; } } } sys->epot = epot; }
void Pair_LJ::ComputeForce(Atoms *atom) { double epot; #if defined(_OPENMP) #pragma omp parallel reduction(+:epot) #endif { double c12,c6,boxby2,rcsq; double *fx, *fy, *fz; double *rx, *ry, *rz; int i, tid, fromidx, toidx, natoms, nthreads; /* precompute some constants */ c12 = 4.0*epsilon*pow(sigma,12.0); c6 = 4.0*epsilon*pow(sigma, 6.0); rcsq= atom->GetRadCut() * atom->GetRadCut(); boxby2 = 0.5*atom->GetBoxSize(); natoms = atom->GetNAtoms(); epot = 0.0; /* let each thread operate on a different part of the enlarged force array */ #if defined(_OPENMP) nthreads=omp_get_num_threads(); tid=omp_get_thread_num(); #else nthreads=1; tid=0; #endif fx=atom->GetForce() + (3*tid*natoms); azzero(fx,3*natoms); fy=atom->GetForce() + ((3*tid+1)*natoms); fz=atom->GetForce() + ((3*tid+2)*natoms); rx=atom->GetPosition(); ry=atom->GetPosition() + natoms; rz=atom->GetPosition() + 2*natoms; int x; /* self interaction of atoms in cell */ for(i=0; i < atom->GetNCells(); i += nthreads) { int j; // cell_t *c1; j = x = i + tid; if (j >= (atom->GetNCells())) break; // c1=atom->clist + j; // afc=getlist(j) for (j=0; j < atom->GetCellNAtoms(x)-1; ++j) { // for (j=0; j < GetCellData()-1; ++j) { int ii,k; double rx1, ry1, rz1; // ii=c1->idxlist[j]; ii=atom->GetCellIndex(x,j); rx1=rx[ii]; ry1=ry[ii]; rz1=rz[ii]; for(k=j+1; k < atom->GetCellNAtoms(x); ++k) { int jj; double rx2,ry2,rz2,rsq; jj=atom->GetCellIndex(x,k); /* get distance between particle i and j */ rx2=pbc(rx1 - rx[jj], boxby2, atom->GetBoxSize()); ry2=pbc(ry1 - ry[jj], boxby2, atom->GetBoxSize()); rz2=pbc(rz1 - rz[jj], boxby2, atom->GetBoxSize()); rsq = rx2*rx2 + ry2*ry2 + rz2*rz2; /* compute force and energy if within cutoff */ if (rsq < rcsq) { double r6,rinv,ffac; rinv=1.0/rsq; r6=rinv*rinv*rinv; ffac = (12.0*c12*r6 - 6.0*c6)*r6*rinv; epot += r6*(c12*r6 - c6); fx[ii] += rx2*ffac; fy[ii] += ry2*ffac; fz[ii] += rz2*ffac; fx[jj] -= rx2*ffac; fy[jj] -= ry2*ffac; fz[jj] -= rz2*ffac; } } } } /* interaction of atoms in different cells */ for(i=0; i < atom->GetNPairs(); i += nthreads) { int j; // const cell_t *c1, *c2; j = x = i + tid; if (x >= (atom->GetNPairs())) break; // c1=atom->clist + atom->plist[2*x]; // c2=atom->clist + atom->plist[2*x+1]; for (j=0; j < atom->GetCellNAtoms(atom->GetPairItem(2*x)); ++j) { int ii, k; double rx1, ry1, rz1; ii=atom->GetCellIndex(atom->GetPairItem(2*x),j); rx1=rx[ii]; ry1=ry[ii]; rz1=rz[ii]; for(k=0; k < atom->GetCellNAtoms(atom->GetPairItem(2*x+1)); ++k) { int jj; double rx2,ry2,rz2,rsq; // jj=c2->idxlist[k]; jj = atom->GetCellIndex(atom->GetPairItem(2*x+1),k); /* get distance between particle i and j */ rx2=pbc(rx1 - rx[jj], boxby2, atom->GetBoxSize()); ry2=pbc(ry1 - ry[jj], boxby2, atom->GetBoxSize()); rz2=pbc(rz1 - rz[jj], boxby2, atom->GetBoxSize()); rsq = rx2*rx2 + ry2*ry2 + rz2*rz2; /* compute force and energy if within cutoff */ if (rsq < rcsq) { double r6,rinv,ffac; rinv=1.0/rsq; r6=rinv*rinv*rinv; ffac = (12.0*c12*r6 - 6.0*c6)*r6*rinv; epot += r6*(c12*r6 - c6); fx[ii] += rx2*ffac; fy[ii] += ry2*ffac; fz[ii] += rz2*ffac; fx[jj] -= rx2*ffac; fy[jj] -= ry2*ffac; fz[jj] -= rz2*ffac; } } } } /* before reducing the forces, we have to make sure that all threads are done adding to them. */ #if defined (_OPENMP) #pragma omp barrier #endif /* set equal chunks of index ranges */ i = 1 + (3*natoms / nthreads); fromidx = tid * i; toidx = fromidx + i; if (toidx > 3*natoms) toidx = 3*natoms; /* reduce forces from threads with tid != 0 into the storage of the first thread. since we have threads already spawned, we do this in parallel. */ for (i=1; i < nthreads; ++i) { int offs, j; offs = 3*i*natoms; for (j=fromidx; j < toidx; ++j) { // atom->frc[j] += atom->frc[offs+j]; atom->SetForce(j,atom->GetForce(j)+atom->GetForce(offs+j)); } } } atom->SetPotEnergy(epot); }