bool AtomExtruder::extrudeAtoms(
  common::Structure & structure,
  const size_t maxIterations,
  const double tolerance) const
{

  const size_t numAtoms = structure.getNumAtoms();

  ::std::vector<common::Atom *> atomsWithRadii;

  for(size_t i = 0; i < numAtoms; ++i)
  {
    common::Atom & atom = structure.getAtom(i);
    if(atom.getRadius() != 0.0)
    {
      atomsWithRadii.push_back(&atom);
    }
  }

  // Calculate seaparation matrix
  ::arma::mat sepSqMtx(atomsWithRadii.size(), atomsWithRadii.size());

  double radius1;
  for(size_t row = 0; row < atomsWithRadii.size(); ++row)
  {
    radius1 = atomsWithRadii[row]->getRadius();
    for(size_t col = row; col < atomsWithRadii.size(); ++col)
    {
      sepSqMtx(row, col) = radius1 + atomsWithRadii[col]->getRadius();
      sepSqMtx(row, col) *= sepSqMtx(row, col);
    }
  }

  sepSqMtx = ::arma::symmatu(sepSqMtx);

  return extrudeAtoms(structure.getDistanceCalculator(), atomsWithRadii, sepSqMtx, tolerance, maxIterations);
}
Exemple #2
0
VoronoiSlabGenerator::Slab::SlabData::SlabData(
    const common::Structure & structure) :
    distCalc(structure.getDistanceCalculator()), unitCell(
        structure.getUnitCell())
{
}
bool
LennardJones::evaluate(const common::Structure & structure,
    SimplePairPotentialData & data) const
{
  using namespace utility::cart_coords_enum;
  using ::std::vector;
  using ::std::pow;
  using ::std::sqrt;

  double rSq;
  double prefactor;
  double sigmaOModR, invRM, invRN;
  double dE, modR, modF, interaction;
  size_t speciesI, speciesJ; // Species indices
  ::arma::vec3 f; // Displacement and force vectors
  ::arma::vec3 posI, posJ; // Position vectors

  resetAccumulators(data);

  vector< ::arma::vec3> imageVectors;

  const common::DistanceCalculator & distCalc =
      structure.getDistanceCalculator();

  bool problemDuringCalculation = false;

  // Loop over all particle pairs (including self-interaction)
  for(size_t i = 0; i < data.numParticles; ++i)
  {
    if(data.species[i] == DataType::IGNORE_ATOM)
      continue;
    else
      speciesI = static_cast< size_t>(data.species[i]);
    posI = data.pos.col(i);

    for(size_t j = i; j < data.numParticles; ++j)
    {
      if(data.species[j] == DataType::IGNORE_ATOM)
        continue;
      else
        speciesJ = static_cast< size_t>(data.species[j]);
      posJ = data.pos.col(j);

      imageVectors.clear();
      if(!distCalc.getVecsBetween(posI, posJ, rCutoff(speciesI, speciesJ),
          imageVectors, MAX_INTERACTION_VECTORS, MAX_CELL_MULTIPLES))
      {
        // We reached the maximum number of interaction vectors so indicate that there was a problem
        problemDuringCalculation = true;
      }

      // Used as a prefactor depending if the particles i and j are in fact the same
      interaction = (i == j) ? 0.5 : 1.0;
      prefactor = 4.0 * myEpsilon(speciesI, speciesJ);

      BOOST_FOREACH(const ::arma::vec & r, imageVectors)
      {
        // Get the distance squared
        rSq = dot(r, r);

        // Check that distance isn't near the 0 as this will cause near-singular values
        if(rSq > MIN_SEPARATION_SQ)
        {
          modR = sqrt(rSq);

          sigmaOModR = mySigma(speciesI, speciesJ) / modR;

          invRN = pow(sigmaOModR, myN);
          // Deal with special case where N is 2 times M avoiding second pow call
          invRM = myM == 2.0 * myN ? invRN * invRN : pow(sigmaOModR, myM);
          invRN *= myBeta(speciesI, speciesJ);

          // Calculate the energy delta
          dE = prefactor * (invRM - invRN) - eShift(speciesI, speciesJ)
              + (modR - rCutoff(speciesI, speciesJ))
                  * fShift(speciesI, speciesJ);

          // Magnitude of the force
          modF = prefactor * (myM * invRM - myN * invRN) / modR
              - fShift(speciesI, speciesJ);
          f = modF / modR * r;

          // Make sure we get energy/force correct for self-interaction
          f *= interaction;
          dE *= interaction;

          // Update system values
          // energy
          data.internalEnergy += dE;
          // force
          data.forces.col(i) -= f;
          if(i != j)
            data.forces.col(j) += f;

          // stress, diagonal is element wise multiplication of force and position
          // vector components
          data.stressMtx.diag() -= f % r;

          data.stressMtx(Y, Z) -= 0.5 * (f(Y) * r(Z) + f(Z) * r(Y));
          data.stressMtx(Z, X) -= 0.5 * (f(Z) * r(X) + f(X) * r(Z));
          data.stressMtx(X, Y) -= 0.5 * (f(X) * r(Y) + f(Y) * r(X));
        }
      }
    }
  }