Exemplo n.º 1
0
HostBoxes* initHostBoxesAos(SimFlat* sim)
{
   HostBoxes* boxes;

   boxes = malloc(sizeof(HostBoxes));

   boxes->nTotalBoxes = sim->boxes->nTotalBoxes;
   boxes->nLocalBoxes = sim->boxes->nLocalBoxes;

   int nMaxInBox = 0;
   int boxWithMax = 0;
   for (int iBox=0;iBox<boxes->nTotalBoxes;iBox++)
   {
      if (sim->boxes->nAtoms[iBox] > nMaxInBox)
      {
         nMaxInBox = sim->boxes->nAtoms[iBox];
         boxWithMax = iBox;
      }
   }
   printf("Max atom count %d in box %d\n", nMaxInBox, boxWithMax);

   boxes->nLocalBoxesNeighborSize = sim->boxes->nLocalBoxes*NUMNEIGHBORS*sizeof(cl_int);
   boxes->nLocalBoxesRealSize = sim->boxes->nLocalBoxes*sizeof(cl_real);
   boxes->nTotalBoxesIntSize = sim->boxes->nTotalBoxes*sizeof(cl_int);

   boxes->neighborList = malloc(boxes->nLocalBoxesNeighborSize);
   boxes->nNeighbors = malloc(boxes->nLocalBoxesIntSize);
   boxes->nAtoms     = malloc(boxes->nTotalBoxesIntSize);

   boxes->boxSize    = malloc(sizeof(cl_real4));
   boxes->invBoxSize    = malloc(sizeof(cl_real4));


   for (int j=0;j<3;j++)
   {
      boxes->boxSize[j] = sim->boxes->boxSize[j];
      boxes->invBoxSize[j] = sim->boxes->invBoxSize[j];
   }

   for (int iBox=0;iBox<sim->boxes->nLocalBoxes;iBox++)
   {

      int* nbrBoxes;
      getNeighborBoxes(sim->boxes,iBox, nbrBoxes);

      boxes->nAtoms[iBox] = sim->boxes->nAtoms[iBox];

      int j;
      boxes->nNeighbors[iBox] = nbrBoxes[-1];
      for (int j=0;j<boxes->nNeighbors[iBox];j++)
      {
         boxes->neighborList[NUMNEIGHBORS*iBox + j] = nbrBoxes[j];
      }
   }

   return boxes;
}
Exemplo n.º 2
0
int LJ(void *inS) {
  /**
   * calculates forces for the 12-6 lennard jones potential **/
  /**
   * Notes on LJ:
   *
   * http://en.wikipedia.org/wiki/Lennard_Jones_potential
   *
   * LJ is a simple potential of the form:
   *
   * e_lj(r) = 4*epsilon*((sigma/r)^12 - (sigma/r)^6)
   * F(r) = 4*epsilon*(12*sigma^12/r^13 - 6*sigma^6/r^7)
   *
   * epsilon and sigma are the adjustable parameters in the potential.
   *    epsilon = well depth
   *    sigma   = hard sphere diameter
   *
   * You can also adjust the 12 & 6, but few people do.
   *
   * Some typical values for epsilon and sigma:
   *
   *   material            epsilon            sigma   
   *     N                 36.20 K             3.299 A
   *     O                 44.06 K             2.956 A
   **/
  simulation_t *s = (simulation_t *) inS;
  int ii, ij, i, j, jTmp;
  real_t r2, r, r6, r7;
  real_t s6;
  real_t f;
  int nIBox;
  int nJBox;
  int *nbrBoxes;
  domain_t *iDomain;
  domain_t *jDomain;
  int iBox, jBox;
  real_t dx, dy, dz;
  ljpotential_t *pot;
  real_t sigma = -1;
  real_t epsilon = -1;
  real_t rcut=-1;
  real_t r2cut = -1;
  double etot;
  
  pot = (ljpotential_t *) s->pot;
  sigma = pot->sigma;
  epsilon = pot->epsilon;
  rcut = pot->cutoff;
  r2cut = rcut*rcut;

  /**
   * point to energy and force and zero them out **/
  etot = 0.0;
  s->e = (real_t) 0.0;

  for(i=0; i<s->boxes.nboxes; i++) {
    zeroForcesInBox(s,i);
  }
  s6 = sigma*sigma*sigma*sigma*sigma*sigma;


  /**
   * The more I read this, the more it seems that I should transfer
   * atom position / force data to the box structure so that the
   * atoms in a box will be contiguous in memory.
   *
   * Right now the atoms are part of the overall simulation structure.
   * This means that potentially two atoms within a box may be widely
   * separated in main memory.  
   **/
  
  for(iBox=0; iBox<s->boxes.nboxes; iBox++) /* loop over all boxes in system */
    {
      iDomain = s->boxes.domains[iBox];
      nIBox = *(iDomain->nAtoms);
      if ( ! nIBox) continue;

      nbrBoxes = getNeighborBoxes(s,iBox);

      for(jTmp=0; jTmp<NUMNEIGHBORS; jTmp++) /* loop over neighbor boxes */
	{
	  jBox = nbrBoxes[jTmp];
	  if(jBox<0) break; /* done with neighbor boxes */

	  jDomain = s->boxes.domains[jBox];
	  nJBox = *(jDomain->nAtoms);
	  if ( ! nJBox) continue;
	  
	  for(ii=0; ii<nIBox; ii++) /* loop over atoms in iBox */
	    {
	      i = iDomain->id[ii];  /* the ij-th atom in iBox */
	      for(ij=0; ij<nJBox; ij++)  /* loop over atoms in iBox */
		{
		  j = jDomain->id[ij];  /* the ij-th atom in iBox */
		  if ( j <= i ) continue;
	  
		  /** dist2(r2,iDomain,jDomain,ii,ij,dx,dy,dz);**/

		  dx = iDomain->x[ii]-jDomain->x[ij];
		  dy = iDomain->y[ii]-jDomain->y[ij];
		  dz = iDomain->z[ii]-jDomain->z[ij];
		  r2 = dx*dx + dy*dy + dz*dz;
		  if ( r2 > r2cut) continue;
	  
		  /**
		   * Important note:
		   *
		   * from this point on r actually refers to 1.0/r
		   *
		   **/
		  r2 =(real_t)1.0/r2;
		  r = sqrt(r2);
		  r6 = (r2*r2*r2);
		  r7 = r6*r;
		  etot += r6*(s6*r6 - 1.0); 
		  f = 4.0*epsilon*s6*r7*(12.0*s6*r6 - 6.0);
		  iDomain->fx[ii] += dx*f*r;
		  iDomain->fy[ii] += dy*f*r;
		  iDomain->fz[ii] += dz*f*r;

		  jDomain->fx[ij] -= dx*f*r;
		  jDomain->fy[ij] -= dy*f*r;
		  jDomain->fz[ij] -= dz*f*r;

		} /* loop over atoms in iBox */
	    } /* loop over atoms in iBox */
	} /* loop over neighbor boxes */

    } /* loop over all boxes in system */

  etot = etot*4.0*epsilon*s6;
  s->e = (real_t) etot;
  return 0;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
/// 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)
{
   //OPT: loop invariant references
   Atoms* atoms = s->atoms;
   LinkCell* boxes = s->boxes;
   int nLocalBoxes = boxes->nLocalBoxes;
   int nTotalBoxes = boxes->nTotalBoxes;
   int* nAtoms = boxes->nAtoms;
   real3* atoms_r = atoms->r;
   real3* atoms_f = atoms->f;
   real_t* atoms_U = atoms->U;

   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;

   // zero forces / energy / rho /rhoprime
   real_t etot = 0.0;
   memset(atoms_f,  0, nTotalBoxes*MAXATOMS*sizeof(real3));
   memset(atoms_U,  0, nTotalBoxes*MAXATOMS*sizeof(real_t));
   memset(pot->dfEmbed, 0, nTotalBoxes*MAXATOMS*sizeof(real_t));
   memset(pot->rhobar,  0, nTotalBoxes*MAXATOMS*sizeof(real_t));

   int nbrBoxes[27];
   // loop over local boxes
   for (int iBox=0; iBox<nLocalBoxes; iBox++)
   {
      int nIBox = nAtoms[iBox];
      int nNbrBoxes = getNeighborBoxes(boxes, iBox, nbrBoxes);
      // loop over neighbor boxes of iBox (some may be halo boxes)
      for (int jTmp=0; jTmp<nNbrBoxes; jTmp++)
      {
         int jBox = nbrBoxes[jTmp];
         if (jBox < iBox ) continue;

         int nJBox = nAtoms[jBox];
         // loop over atoms in iBox
         for (int iOff=MAXATOMS*iBox,ii=0; ii<nIBox; ii++,iOff++)
         {
            // loop over atoms in jBox
            for (int jOff=MAXATOMS*jBox,ij=0; ij<nJBox; ij++,jOff++)
            {
               if ( (iBox==jBox) &&(ij <= ii) ) continue;

               double r2 = 0.0;
               real3 dr;
//OPT: loop unrolling
//               for (int k=0; k<3; k++)
//               {
//                  dr[k]=atoms_r[iOff][k]-atoms_r[jOff][k];
//                  r2+=dr[k]*dr[k];
//               }
               double dr0 = atoms_r[iOff][0]-atoms_r[jOff][0];
               r2+=dr0*dr0;
               double dr1 = atoms_r[iOff][1]-atoms_r[jOff][1];
               r2+=dr1*dr1;
               double dr2 = atoms_r[iOff][2]-atoms_r[jOff][2];
               r2+=dr2*dr2;
//End of OPT: loop unrolling

               if(r2>rCut2) continue;

               double r = sqrt(r2);

               real_t phiTmp, dPhi, rhoTmp, dRho;
               interpolate(pot->phi, r, &phiTmp, &dPhi);
               interpolate(pot->rho, r, &rhoTmp, &dRho);

//OPT: loop unrolling
//               for (int k=0; k<3; k++)
//               {
//                  atoms_f[iOff][k] -= dPhi*dr[k]/r;
//                  atoms_f[jOff][k] += dPhi*dr[k]/r;
//               }
               real_t cal = dPhi*dr0/r;
               atoms_f[iOff][0] -= cal;
               atoms_f[jOff][0] += cal;
               cal = dPhi*dr1/r;
               atoms_f[iOff][1] -= cal;
               atoms_f[jOff][1] += cal;
               cal = dPhi*dr2/r;
               atoms_f[iOff][2] -= cal;
               atoms_f[jOff][2] += cal;
//End of OPT: loop unrolling

               // update energy terms
               // calculate energy contribution based on whether
               // the neighbor box is local or remote
               if (jBox < nLocalBoxes)
                  etot += phiTmp;
               else
                  etot += 0.5*phiTmp;

               atoms_U[iOff] += 0.5*phiTmp;
               atoms_U[jOff] += 0.5*phiTmp;

               // accumulate rhobar for each atom
               pot->rhobar[iOff] += rhoTmp;
               pot->rhobar[jOff] += 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
   for (int iBox=0; iBox<nLocalBoxes; iBox++)
   {
      int iOff;
      int nIBox = nAtoms[iBox];

      // loop over atoms in iBox
      for (int iOff=MAXATOMS*iBox,ii=0; ii<nIBox; ii++,iOff++)
      {
         real_t fEmbed, dfEmbed;
         interpolate(pot->f, pot->rhobar[iOff], &fEmbed, &dfEmbed);
         pot->dfEmbed[iOff] = dfEmbed; // save derivative for halo exchange
         etot += fEmbed; 
         atoms_U[iOff] += 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
   for (int iBox=0; iBox<nLocalBoxes; iBox++)
   {
      int nIBox = nAtoms[iBox];
      int nNbrBoxes = getNeighborBoxes(boxes, iBox, nbrBoxes);
      // loop over neighbor boxes of iBox (some may be halo boxes)
      for (int jTmp=0; jTmp<nNbrBoxes; jTmp++)
      {
         int jBox = nbrBoxes[jTmp];
         if(jBox < iBox) continue;

         int nJBox = nAtoms[jBox];
         // loop over atoms in iBox
         for (int iOff=MAXATOMS*iBox,ii=0; ii<nIBox; ii++,iOff++)
         {
            // loop over atoms in jBox
            for (int jOff=MAXATOMS*jBox,ij=0; ij<nJBox; ij++,jOff++)
            { 
               if ((iBox==jBox) && (ij <= ii))  continue;

               double r2 = 0.0;
               real3 dr;
//OPT: loop unrolling
//               for (int k=0; k<3; k++)
//               {
//                  dr[k]=atoms_r[iOff][k]-atoms_r[jOff][k];
//                  r2+=dr[k]*dr[k];
//               }
               real_t dr0 = atoms_r[iOff][0]-atoms_r[jOff][0];
               r2 += dr0*dr0;
               real_t dr1 = atoms_r[iOff][1]-atoms_r[jOff][1];
               r2 += dr1*dr1;
               real_t dr2 = atoms_r[iOff][2]-atoms_r[jOff][2];
               r2 += dr2*dr2;
//End of OPT: loop unrolling

               if(r2>=rCut2) continue;

               real_t r = sqrt(r2);

               real_t rhoTmp, dRho;
               interpolate(pot->rho, r, &rhoTmp, &dRho);

//OPT: loop unrolling
//               for (int k=0; k<3; k++)
//               {
//                  atoms_f[iOff][k] -= (pot->dfEmbed[iOff]+pot->dfEmbed[jOff])*dRho*dr[k]/r;
//                  atoms_f[jOff][k] += (pot->dfEmbed[iOff]+pot->dfEmbed[jOff])*dRho*dr[k]/r;
//               }
               real_t cal = (pot->dfEmbed[iOff]+pot->dfEmbed[jOff])*dRho*dr0/r;
               atoms_f[iOff][0] -= cal;
               atoms_f[jOff][0] += cal;
               cal = (pot->dfEmbed[iOff]+pot->dfEmbed[jOff])*dRho*dr1/r;
               atoms_f[iOff][1] -= cal;
               atoms_f[jOff][1] += cal;
               cal = (pot->dfEmbed[iOff]+pot->dfEmbed[jOff])*dRho*dr2/r;
               atoms_f[iOff][2] -= cal;
               atoms_f[jOff][2] += cal;
//End of OPT: loop unrolling
            } // 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;
}
Exemplo n.º 5
0
/// 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;

   // zero forces / energy / rho /rhoprime
   real_t etot = 0.0;
   memset(s->atoms->f,  0, s->boxes->nTotalBoxes*MAXATOMS*sizeof(real3));
   memset(s->atoms->U,  0, s->boxes->nTotalBoxes*MAXATOMS*sizeof(real_t));
   memset(pot->dfEmbed, 0, s->boxes->nTotalBoxes*MAXATOMS*sizeof(real_t));
   memset(pot->rhobar,  0, s->boxes->nTotalBoxes*MAXATOMS*sizeof(real_t));

   // virial stress computation added here
   for (int m = 0;m<9;m++) 
   {
      s->defInfo->stress[m] = 0.0;
   }

   int nbrBoxes[27];
   // loop over local boxes
   for (int iBox=0; iBox<s->boxes->nLocalBoxes; iBox++)
   {
      int nIBox = s->boxes->nAtoms[iBox];
      int nNbrBoxes = getNeighborBoxes(s->boxes, iBox, nbrBoxes);
      // loop over neighbor boxes of iBox (some may be halo boxes)
      for (int jTmp=0; jTmp<nNbrBoxes; jTmp++)
      {
         int jBox = nbrBoxes[jTmp];
         if (jBox < iBox ) continue;

         int nJBox = s->boxes->nAtoms[jBox];
         // loop over atoms in iBox
         for (int iOff=MAXATOMS*iBox,ii=0; ii<nIBox; ii++,iOff++)
         {
            // loop over atoms in jBox
            for (int jOff=MAXATOMS*jBox,ij=0; ij<nJBox; ij++,jOff++)
            {
               if ( (iBox==jBox) &&(ij <= ii) ) continue;

               double 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) continue;

               double 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;
                  s->atoms->f[jOff][k] += dPhi*dr[k]/r;
               }

               for (int i=0; i<3; i++)
               {
                  for (int j=0; j<3; j++)
                  {
                     int m = 3*i + j;
                     s->defInfo->stress[m] += 1.0*dPhi*dr[i]*dr[j]/r;
                  }
               }

               // update energy terms
               // calculate energy contribution based on whether
               // the neighbor box is local or remote
               if (jBox < s->boxes->nLocalBoxes)
                  etot += phiTmp;
               else
                  etot += 0.5*phiTmp;

               s->atoms->U[iOff] += 0.5*phiTmp;
               s->atoms->U[jOff] += 0.5*phiTmp;

               // accumulate rhobar for each atom
               pot->rhobar[iOff] += rhoTmp;
               pot->rhobar[jOff] += 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
   for (int iBox=0; iBox<s->boxes->nLocalBoxes; iBox++)
   {
      int iOff;
      int nIBox =  s->boxes->nAtoms[iBox];

      // loop over atoms in iBox
      for (int iOff=MAXATOMS*iBox,ii=0; ii<nIBox; ii++,iOff++)
      {
         real_t fEmbed, dfEmbed;
         interpolate(pot->f, pot->rhobar[iOff], &fEmbed, &dfEmbed);
         pot->dfEmbed[iOff] = dfEmbed; // save derivative for halo exchange
         etot += fEmbed; 
         s->atoms->U[iOff] += fEmbed;
         int iSpecies = s->atoms->iSpecies[iOff];
         real_t invMass = 1.0/s->species[iSpecies].mass;
         for (int i=0; i<3; i++)
         {
            for (int j=0; j<3; j++)
            {
               int m = 3*i + j;
               s->defInfo->stress[m] -= s->atoms->p[iOff][i]*s->atoms->p[iOff][j]*invMass;
            }
         }
      }
   }

   // 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
   for (int iBox=0; iBox<s->boxes->nLocalBoxes; iBox++)
   {
      int nIBox =  s->boxes->nAtoms[iBox];
      int nNbrBoxes = getNeighborBoxes(s->boxes, iBox, nbrBoxes);
      // loop over neighbor boxes of iBox (some may be halo boxes)
      for (int jTmp=0; jTmp<nNbrBoxes; jTmp++)
      {
         int jBox = nbrBoxes[jTmp];
         if(jBox < iBox) continue;

         int nJBox = s->boxes->nAtoms[jBox];
         // loop over atoms in iBox
         for (int iOff=MAXATOMS*iBox,ii=0; ii<nIBox; ii++,iOff++)
         {
            // loop over atoms in jBox
            for (int jOff=MAXATOMS*jBox,ij=0; ij<nJBox; ij++,jOff++)
            { 
               if ((iBox==jBox) && (ij <= ii))  continue;

               double 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) continue;

               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;
                  s->atoms->f[jOff][k] += (pot->dfEmbed[iOff]+pot->dfEmbed[jOff])*dRho*dr[k]/r;
               }

               for (int i=0; i<3; i++)
               {
                  for (int j=0; j<3; j++)
                  {
                     int m = 3*i + j;
                     s->defInfo->stress[m] += 1.0*(pot->dfEmbed[iOff]+pot->dfEmbed[jOff])*dRho*dr[i]*dr[j]/r;
                  }
               }

            } // loop over atoms in jBox
         } // loop over atoms in iBox
      } // loop over neighbor boxes
   } // loop over local boxes

   s->ePotential = (real_t) etot;

   for (int m = 0;m<9;m++) 
   {
      s->defInfo->stress[m] = s->defInfo->stress[m]/s->defInfo->globalVolume;
   }

   return 0;
}
Exemplo n.º 6
0
HostBoxes* initHostBoxesSoa(SimFlat* sim)
{
   HostBoxes* boxes;

   boxes = malloc(sizeof(HostBoxes));

   boxes->boxSize      = malloc(3*sizeof(cl_real));
   boxes->invBoxSize   = malloc(3*sizeof(cl_real));

   boxes->nTotalBoxes = sim->boxes->nTotalBoxes;
   boxes->nHaloBoxes = sim->boxes->nHaloBoxes;
   boxes->nLocalBoxes = sim->boxes->nLocalBoxes;

   printf("Allocating space on host for %d local and %d halo boxes\n", boxes->nLocalBoxes, boxes->nHaloBoxes);

   boxes->nLocalBoxesNeighborSize = boxes->nLocalBoxes*NUMNEIGHBORS*sizeof(cl_int);
   boxes->nLocalBoxesRealSize     = boxes->nLocalBoxes*sizeof(cl_real);
   boxes->nLocalBoxesIntSize      = boxes->nLocalBoxes*sizeof(cl_int);

   boxes->nTotalBoxesIntSize      = boxes->nTotalBoxes*sizeof(cl_int);

   for (int j=0;j<3;j++)
   {
      boxes->boxSize[j]    = sim->boxes->boxSize[j];
      boxes->invBoxSize[j] = sim->boxes->invBoxSize[j];
   }

   // only need neighbor lists for local boxes
   boxes->neighborList = malloc(boxes->nLocalBoxesNeighborSize);
   boxes->nNeighbors   = malloc(boxes->nLocalBoxesIntSize);
   for (int iBox=0;iBox<sim->boxes->nLocalBoxes;iBox++)
   {

      int nbrBoxes[27];
      boxes->nNeighbors[iBox] = getNeighborBoxes(sim->boxes,iBox, nbrBoxes);
      // check if any boxes are missing neighbors
      if (boxes->nNeighbors[iBox] < 27)
         printf("Box %d has only %d neighbors\n", iBox, boxes->nNeighbors[iBox]);

      for (int j=0;j<boxes->nNeighbors[iBox];j++)
      {
         boxes->neighborList[NUMNEIGHBORS*iBox + j] = nbrBoxes[j];
      }

   }

   // need nAtoms for all boxes
   boxes->nAtoms       = malloc(boxes->nTotalBoxesIntSize);
   for (int iBox=0;iBox<sim->boxes->nTotalBoxes;iBox++)
   {
      boxes->nAtoms[iBox] = sim->boxes->nAtoms[iBox];
   }

   // cehck box occupancy for all local boxes
   int nMaxInBox = 0;
   int boxWithMax = 0;
   for (int iBox=0;iBox<boxes->nLocalBoxes;iBox++)
   {
      if (sim->boxes->nAtoms[iBox] > nMaxInBox)
      {
         nMaxInBox = sim->boxes->nAtoms[iBox];
         boxWithMax = iBox;
      }
   }
   printf("Max atom count %d in box %d\n", nMaxInBox, boxWithMax);

   return boxes;
}