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); }
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)); } } } }