示例#1
0
void ComputeForces()
{
  for(int i = 0; i < numCells; ++i) {
    Cell *cell = &cells[i];
    int np = cnumPars[i];
    for(int j = 0; j < np; ++j) {
      cell->density[j % PARTICLES_PER_CELL] = 0.0;
      cell->a[j % PARTICLES_PER_CELL] = externalAcceleration;
      //move pointer to next cell in list if end of array is reached
      if(j % PARTICLES_PER_CELL == PARTICLES_PER_CELL-1) {
        cell = cell->next;
      }
    }
  }

  int neighCells[3*3*3];

  int cindex = 0;
  for(int ck = 0; ck < nz; ++ck) {
    for(int cj = 0; cj < ny; ++cj) {
      for(int ci = 0; ci < nx; ++ci, ++cindex) {
        int np = cnumPars[cindex];
        if(np == 0)
          continue;

        int numNeighCells = GetNeighborCells(ci, cj, ck, neighCells);

        Cell *cell = &cells[cindex];
        for(int ipar = 0; ipar < np; ++ipar) {
          for(int inc = 0; inc < numNeighCells; ++inc) {
            int cindexNeigh = neighCells[inc];
            Cell *neigh = &cells[cindexNeigh];
            int numNeighPars = cnumPars[cindexNeigh];
            for(int iparNeigh = 0; iparNeigh < numNeighPars; ++iparNeigh) {
              //Check address to make sure densities are computed only once per pair
              if(&neigh->p[iparNeigh % PARTICLES_PER_CELL] < &cell->p[ipar % PARTICLES_PER_CELL])
              {
                fptype distSq = (cell->p[ipar % PARTICLES_PER_CELL] - neigh->p[iparNeigh % PARTICLES_PER_CELL]).GetLengthSq();
                if(distSq < hSq)
                {
                  fptype t = hSq - distSq;
                  fptype tc = t*t*t;
                  cell->density[ipar % PARTICLES_PER_CELL] += tc;
                  neigh->density[iparNeigh % PARTICLES_PER_CELL] += tc;
                }
              }
              //move pointer to next cell in list if end of array is reached
              if(iparNeigh % PARTICLES_PER_CELL == PARTICLES_PER_CELL-1) {
                neigh = neigh->next;
              }
            }
          }
          //move pointer to next cell in list if end of array is reached
          if(ipar % PARTICLES_PER_CELL == PARTICLES_PER_CELL-1) {
            cell = cell->next;
          }
        }
      }
    }
  }
  const fptype tc = hSq*hSq*hSq;
  for(int i = 0; i < numCells; ++i) {
    Cell *cell = &cells[i];
    int np = cnumPars[i];
    for(int j = 0; j < np; ++j) {
      cell->density[j % PARTICLES_PER_CELL] += tc;
      cell->density[j % PARTICLES_PER_CELL] *= densityCoeff;
      //move pointer to next cell in list if end of array is reached
      if(j % PARTICLES_PER_CELL == PARTICLES_PER_CELL-1) {
        cell = cell->next;
      }
    }
  }

  cindex = 0;
  for(int ck = 0; ck < nz; ++ck) {
    for(int cj = 0; cj < ny; ++cj) {
      for(int ci = 0; ci < nx; ++ci, ++cindex) {
        int np = cnumPars[cindex];
        if(np == 0)
          continue;

        int numNeighCells = GetNeighborCells(ci, cj, ck, neighCells);

        Cell *cell = &cells[cindex];
        for(int ipar = 0; ipar < np; ++ipar) {
          for(int inc = 0; inc < numNeighCells; ++inc) {
            int cindexNeigh = neighCells[inc];
            Cell *neigh = &cells[cindexNeigh];
            int numNeighPars = cnumPars[cindexNeigh];
            for(int iparNeigh = 0; iparNeigh < numNeighPars; ++iparNeigh) {
              //Check address to make sure forces are computed only once per pair
              if(&neigh->p[iparNeigh % PARTICLES_PER_CELL] < &cell->p[ipar % PARTICLES_PER_CELL])
              {
                Vec3 disp = cell->p[ipar % PARTICLES_PER_CELL] - neigh->p[iparNeigh % PARTICLES_PER_CELL];
                fptype distSq = disp.GetLengthSq();
                if(distSq < hSq)
                {
#ifndef ENABLE_DOUBLE_PRECISION
                  fptype dist = sqrtf(std::max(distSq, (fptype)1e-12));
#else
                  fptype dist = sqrt(std::max(distSq, 1e-12));
#endif //ENABLE_DOUBLE_PRECISION
                  fptype hmr = h - dist;

                  Vec3 acc = disp * pressureCoeff * (hmr*hmr/dist) * (cell->density[ipar % PARTICLES_PER_CELL]+neigh->density[iparNeigh % PARTICLES_PER_CELL] - doubleRestDensity);
                  acc += (neigh->v[iparNeigh % PARTICLES_PER_CELL] - cell->v[ipar % PARTICLES_PER_CELL]) * viscosityCoeff * hmr;
                  acc /= cell->density[ipar % PARTICLES_PER_CELL] * neigh->density[iparNeigh % PARTICLES_PER_CELL];

                  cell->a[ipar % PARTICLES_PER_CELL] += acc;
                  neigh->a[iparNeigh % PARTICLES_PER_CELL] -= acc;
                }
              }
              //move pointer to next cell in list if end of array is reached
              if(iparNeigh % PARTICLES_PER_CELL == PARTICLES_PER_CELL-1) {
                neigh = neigh->next;
              }
            }
          }
          //move pointer to next cell in list if end of array is reached
          if(ipar % PARTICLES_PER_CELL == PARTICLES_PER_CELL-1) {
            cell = cell->next;
          }
        }
      }
    }
  }
}