/// \details /// Call functions such as createFccLattice and setTemperature to set up /// initial atom positions and momenta. Atoms* initAtoms(LinkCell* boxes) { Atoms* atoms = comdMalloc(sizeof(Atoms)); int maxTotalAtoms = MAXATOMS*boxes->nTotalBoxes; atoms->gid = (int*) comdMalloc(maxTotalAtoms*sizeof(int)); atoms->iSpecies = (int*) comdMalloc(maxTotalAtoms*sizeof(int)); atoms->r = (real3*) comdMalloc(maxTotalAtoms*sizeof(real3)); atoms->p = (real3*) comdMalloc(maxTotalAtoms*sizeof(real3)); atoms->f = (real3*) comdMalloc(maxTotalAtoms*sizeof(real3)); atoms->U = (real_t*)comdMalloc(maxTotalAtoms*sizeof(real_t)); atoms->nLocal = 0; atoms->nGlobal = 0; for (int iOff = 0; iOff < maxTotalAtoms; iOff++) { atoms->gid[iOff] = 0; atoms->iSpecies[iOff] = 0; zeroReal3(atoms->r[iOff]); zeroReal3(atoms->p[iOff]); zeroReal3(atoms->f[iOff]); atoms->U[iOff] = 0.; } return atoms; }
void comd_forceStep (cncTag_t i, cncTag_t iter, BItem b1, comdCtx *ctx) { struct box *b = b1; if (i == 0) printf("CnC: 0 forceStep %lu, %lu\n", i, iter); int nbrBoxes[27]; int nNbrBoxes = getNeighborBoxes1(b, i, nbrBoxes); for (int iOff=0; iOff< b->nAtoms; iOff++) { zeroReal3(b->atoms.f[iOff]); b->atoms.U[iOff] = 0.; } b->ePot = 0.0; b->eKin = 0.0; // printf("CnC: 1 forceStep %lu, %lu\n", i, iter); cncPrescribe_computeForcefromNeighborsStep(i, nbrBoxes[0], nbrBoxes[1],nbrBoxes[2],nbrBoxes[3],nbrBoxes[4],nbrBoxes[5],nbrBoxes[6],nbrBoxes[7],nbrBoxes[8],nbrBoxes[9],nbrBoxes[10],nbrBoxes[11],nbrBoxes[12],nbrBoxes[14],nbrBoxes[15],nbrBoxes[16],nbrBoxes[17],nbrBoxes[18],nbrBoxes[19],nbrBoxes[20],nbrBoxes[21],nbrBoxes[22],nbrBoxes[23],nbrBoxes[24],nbrBoxes[25],nbrBoxes[26], iter, ctx); if (ctx->doeam) cncPrescribe_computeForcefromNeighborsStep1(i, nbrBoxes[0], nbrBoxes[1],nbrBoxes[2],nbrBoxes[3],nbrBoxes[4],nbrBoxes[5],nbrBoxes[6],nbrBoxes[7],nbrBoxes[8],nbrBoxes[9],nbrBoxes[10],nbrBoxes[11],nbrBoxes[12],nbrBoxes[14],nbrBoxes[15],nbrBoxes[16],nbrBoxes[17],nbrBoxes[18],nbrBoxes[19],nbrBoxes[20],nbrBoxes[21],nbrBoxes[22],nbrBoxes[23],nbrBoxes[24],nbrBoxes[25],nbrBoxes[26], iter, ctx); // printf("CnC: 2 forceStep %lu, %lu\n", i, iter); }
/// \details /// Call functions such as createFccLattice and setTemperature to set up /// initial atom positions and momenta. Atoms* initAtoms(LinkCell* boxes, comdCtx *context) { Atoms *atoms; atoms = cncItemAlloc(sizeof(*atoms)); cncPut_ATOMS(atoms, 1, context); int maxTotalAtoms = MAXATOMS*boxes->nTotalBoxes; atoms->gid = cncItemAlloc(sizeof(*atoms->gid) * maxTotalAtoms); cncPut_GID(atoms->gid, 1, context); atoms->iSpecies = cncItemAlloc(sizeof(*atoms->iSpecies) * maxTotalAtoms); cncPut_ISP(atoms->iSpecies, 1, context); atoms->r = cncItemAlloc(sizeof(*atoms->r) * maxTotalAtoms); cncPut_R(atoms->r, 1, context); atoms->p = cncItemAlloc(sizeof(*atoms->p) * maxTotalAtoms); cncPut_P(atoms->p, 1, context); atoms->f = cncItemAlloc(sizeof(*atoms->f) * maxTotalAtoms); cncPut_F(atoms->f, 1, context); atoms->U = cncItemAlloc(sizeof(*atoms->U) * maxTotalAtoms); cncPut_U(atoms->U, 1, context); atoms->nLocal = 0; atoms->nGlobal = 0; for (int iOff = 0; iOff < maxTotalAtoms; iOff++) { atoms->gid[iOff] = 0; atoms->iSpecies[iOff] = 0; zeroReal3(atoms->r[iOff]); zeroReal3(atoms->p[iOff]); zeroReal3(atoms->f[iOff]); atoms->U[iOff] = 0.; } return atoms; }
/// Calculate potential energy and forces for the EAM potential. /// /// Three steps are required: /// /// -# Loop over all atoms and their neighbors, compute the two-body /// interaction and the electron density at each atom /// -# Loop over all atoms, compute the embedding energy and its /// derivative for each atom /// -# Loop over all atoms and their neighbors, compute the embedding /// energy contribution to the force and add to the two-body force /// int eamForce(SimFlat* s) { EamPotential* pot = (EamPotential*) s->pot; assert(pot); // set up halo exchange and internal storage on first call to forces. if (pot->forceExchange == NULL) { int maxTotalAtoms = MAXATOMS*s->boxes->nTotalBoxes; pot->dfEmbed = comdMalloc(maxTotalAtoms*sizeof(real_t)); pot->rhobar = comdMalloc(maxTotalAtoms*sizeof(real_t)); pot->forceExchange = initForceHaloExchange(s->domain, s->boxes); pot->forceExchangeData = comdMalloc(sizeof(ForceExchangeData)); pot->forceExchangeData->dfEmbed = pot->dfEmbed; pot->forceExchangeData->boxes = s->boxes; } real_t rCut2 = pot->cutoff*pot->cutoff; real_t etot = 0.; // zero forces / energy / rho /rhoprime int fsize = s->boxes->nTotalBoxes*MAXATOMS; //#pragma omp parallel for for (int ii=0; ii<fsize; ii++) { zeroReal3(s->atoms->f[ii]); //s->atoms->U[ii] = 0.;//never used pot->dfEmbed[ii] = 0.; pot->rhobar[ii] = 0.; } int nNbrBoxes = 27; // loop over local boxes //#pragma omp parallel for reduction(+:etot) for(int iBox=0; iBox<s->boxes->nLocalBoxes; iBox++){ int nIBox = s->boxes->nAtoms[iBox]; // loop over neighbor boxes of iBox (some may be halo boxes) for(int jTmp=0; jTmp<nNbrBoxes; jTmp++) { int jBox = s->boxes->nbrBoxes[iBox][jTmp]; int nJBox = s->boxes->nAtoms[jBox]; // loop over atoms in iBox for(int iOff=MAXATOMS*iBox; iOff<(iBox*MAXATOMS+nIBox); iOff++) { // loop over atoms in jBox for(int jOff=MAXATOMS*jBox; jOff<(jBox*MAXATOMS+nJBox); jOff++) { real3 dr; real_t r2 = 0.0; for(int k=0; k<3; k++) { dr[k]=s->atoms->r[iOff][k]-s->atoms->r[jOff][k]; r2+=dr[k]*dr[k]; } if(r2 <= rCut2 && r2 > 0.0) { real_t r = sqrt(r2); real_t phiTmp, dPhi, rhoTmp, dRho; interpolate(pot->phi, r, &phiTmp, &dPhi); interpolate(pot->rho, r, &rhoTmp, &dRho); for(int k=0; k<3; k++) { s->atoms->f[iOff][k] -= dPhi*dr[k]/r; } // Calculate energy contribution //s->atoms->U[iOff] += 0.5*phiTmp;//never used etot += 0.5*phiTmp; // accumulate rhobar for each atom pot->rhobar[iOff] += rhoTmp; } } // loop over atoms in jBox } // loop over atoms in iBox } // loop over neighbor boxes } // loop over local boxes // Compute Embedding Energy // loop over all local boxes //#pragma omp parallel for reduction(+:etot) for (int iBox=0; iBox<s->boxes->nLocalBoxes; iBox++) { int nIBox = s->boxes->nAtoms[iBox]; // loop over atoms in iBox for (int iOff=MAXATOMS*iBox; iOff<(MAXATOMS*iBox+nIBox); iOff++) { real_t fEmbed, dfEmbed; interpolate(pot->f, pot->rhobar[iOff], &fEmbed, &dfEmbed); pot->dfEmbed[iOff] = dfEmbed; // save derivative for halo exchange //s->atoms->U[iOff] += fEmbed;//never used etot += fEmbed; } } // exchange derivative of the embedding energy with repsect to rhobar startTimer(eamHaloTimer); haloExchange(pot->forceExchange, pot->forceExchangeData); stopTimer(eamHaloTimer); // third pass // loop over local boxes //#pragma omp parallel for for (int iBox=0; iBox<s->boxes->nLocalBoxes; iBox++) { int nIBox = s->boxes->nAtoms[iBox]; // loop over neighbor boxes of iBox (some may be halo boxes) for (int jTmp=0; jTmp<nNbrBoxes; jTmp++) { int jBox = s->boxes->nbrBoxes[iBox][jTmp]; int nJBox = s->boxes->nAtoms[jBox]; // loop over atoms in iBox for (int iOff=MAXATOMS*iBox; iOff<(MAXATOMS*iBox+nIBox); iOff++) { // loop over atoms in jBox for (int jOff=MAXATOMS*jBox; jOff<(MAXATOMS*jBox+nJBox); jOff++) { real_t r2 = 0.0; real3 dr; for (int k=0; k<3; k++) { dr[k]=s->atoms->r[iOff][k]-s->atoms->r[jOff][k]; r2+=dr[k]*dr[k]; } if(r2 <= rCut2 && r2 > 0.0) { real_t r = sqrt(r2); real_t rhoTmp, dRho; interpolate(pot->rho, r, &rhoTmp, &dRho); for (int k=0; k<3; k++) { s->atoms->f[iOff][k] -= (pot->dfEmbed[iOff]+pot->dfEmbed[jOff])*dRho*dr[k]/r; } } } // loop over atoms in jBox } // loop over atoms in iBox } // loop over neighbor boxes } // loop over local boxes s->ePotential = (real_t) etot; return 0; }
static int ljForce(SimFlat *s) { LjPotential *pot = (LjPotential *)(s -> pot); real_t sigma = pot -> sigma; real_t epsilon = pot -> epsilon; real_t rCut = pot -> cutoff; real_t rCut2 = rCut * rCut; // zero forces and energy real_t ePot = 0.0; s -> ePotential = 0.0; int fSize = s -> boxes -> nTotalBoxes * 64; for (int ii = 0; ii < fSize; ++ii) { zeroReal3(s -> atoms -> f[ii]); s -> atoms -> U[ii] = 0.0; } real_t s6 = sigma * sigma * sigma * sigma * sigma * sigma; real_t rCut6 = s6 / (rCut2 * rCut2 * rCut2); real_t eShift = 1.0 * rCut6 * (rCut6 - 1.0); int nbrBoxes[27]; // loop over local boxes for (int iBox = 0; iBox < s -> boxes -> nLocalBoxes; iBox++) { int nIBox = s -> boxes -> nAtoms[iBox]; if (nIBox == 0) { continue; } int nNbrBoxes = getNeighborBoxes(s -> boxes,iBox,nbrBoxes); // loop over neighbors of iBox for (int jTmp = 0; jTmp < nNbrBoxes; jTmp++) { int jBox = nbrBoxes[jTmp]; jBox >= 0?((void )0) : __assert_fail("jBox>=0","ljForce.c",159,__PRETTY_FUNCTION__); int nJBox = s -> boxes -> nAtoms[jBox]; if (nJBox == 0) { continue; } // loop over atoms in iBox for (int iOff = iBox * 64, ii = 0; ii < nIBox; (ii++ , iOff++)) { int iId = s -> atoms -> gid[iOff]; // loop over atoms in jBox for (int jOff = 64 * jBox, ij = 0; ij < nJBox; (ij++ , jOff++)) { real_t dr[3]; int jId = s -> atoms -> gid[jOff]; if (jBox < s -> boxes -> nLocalBoxes && jId <= iId) { // don't double count local-local pairs. continue; } real_t r2 = 0.0; for (int m = 0; m < 3; m++) { dr[m] = s -> atoms -> r[iOff][m] - s -> atoms -> r[jOff][m]; r2 += dr[m] * dr[m]; } if (r2 > rCut2) { continue; } // Important note: // from this point on r actually refers to 1.0/r r2 = 1.0 / r2; real_t r6 = s6 * (r2 * r2 * r2); real_t eLocal = r6 * (r6 - 1.0) - eShift; s -> atoms -> U[iOff] += 0.5 * eLocal; s -> atoms -> U[jOff] += 0.5 * eLocal; // calculate energy contribution based on whether // the neighbor box is local or remote if (jBox < s -> boxes -> nLocalBoxes) { ePot += eLocal; } else { ePot += 0.5 * eLocal; } // different formulation to avoid sqrt computation real_t fr = -4.0 * epsilon * r6 * r2 * (12.0 * r6 - 6.0); for (int m = 0; m < 3; m++) { s -> atoms -> f[iOff][m] -= dr[m] * fr; s -> atoms -> f[jOff][m] += dr[m] * fr; } // loop over atoms in jBox } // loop over atoms in iBox } // loop over neighbor boxes } // loop over local boxes in system } ePot = ePot * 4.0 * epsilon; s -> ePotential = ePot; return 0; }
int ljForce(SimFlat* s) { LjPotential* pot = (LjPotential *) s->pot; real_t sigma = pot->sigma; real_t epsilon = pot->epsilon; real_t rCut = pot->cutoff; real_t rCut2 = rCut*rCut; // zero forces and energy real_t ePot = 0.0; s->ePotential = 0.0; int fSize = s->boxes->nTotalBoxes*MAXATOMS; #pragma omp parallel for for (int ii=0; ii<fSize; ++ii) { zeroReal3(s->atoms->f[ii]); s->atoms->U[ii] = 0.; } real_t s6 = sigma*sigma*sigma*sigma*sigma*sigma; real_t rCut6 = s6 / (rCut2*rCut2*rCut2); real_t eShift = POT_SHIFT * rCut6 * (rCut6 - 1.0); int nNbrBoxes = 27; // loop over local boxes #pragma omp parallel for reduction(+:ePot) for (int iBox=0; iBox<s->boxes->nLocalBoxes; iBox++) { int nIBox = s->boxes->nAtoms[iBox]; // loop over neighbors of iBox for (int jTmp=0; jTmp<nNbrBoxes; jTmp++) { int jBox = s->boxes->nbrBoxes[iBox][jTmp]; assert(jBox>=0); int nJBox = s->boxes->nAtoms[jBox]; // loop over atoms in iBox for (int iOff=MAXATOMS*iBox; iOff<(iBox*MAXATOMS+nIBox); iOff++) { // loop over atoms in jBox for (int jOff=jBox*MAXATOMS; jOff<(jBox*MAXATOMS+nJBox); jOff++) { real3 dr; real_t r2 = 0.0; for (int m=0; m<3; m++) { dr[m] = s->atoms->r[iOff][m]-s->atoms->r[jOff][m]; r2+=dr[m]*dr[m]; } if ( r2 <= rCut2 && r2 > 0.0) { // Important note: // from this point on r actually refers to 1.0/r r2 = 1.0/r2; real_t r6 = s6 * (r2*r2*r2); real_t eLocal = r6 * (r6 - 1.0) - eShift; s->atoms->U[iOff] += 0.5*eLocal; ePot += 0.5*eLocal; // different formulation to avoid sqrt computation real_t fr = - 4.0*epsilon*r6*r2*(12.0*r6 - 6.0); for (int m=0; m<3; m++) { s->atoms->f[iOff][m] -= dr[m]*fr; } } } // loop over atoms in jBox } // loop over atoms in iBox } // loop over neighbor boxes } // loop over local boxes in system ePot = ePot*4.0*epsilon; s->ePotential = ePot; return 0; }