OPRGyration::molGyrationDat OPRGyration::getGyrationEigenSystem(const std::tr1::shared_ptr<CRange>& range, const dynamo::SimData* Sim) { //Determine the centre of mass. Watch for periodic images Vector tmpVec; molGyrationDat retVal; retVal.MassCentre = Vector (0,0,0); double totmass = Sim->dynamics.getSpecies(Sim->particleList[*(range->begin())]).getMass(*(range->begin())); std::vector<Vector> relVecs; relVecs.reserve(range->size()); relVecs.push_back(Vector(0,0,0)); //Walk along the chain for (CRange::iterator iPtr = range->begin()+1; iPtr != range->end(); iPtr++) { Vector currRelPos = Sim->particleList[*iPtr].getPosition() - Sim->particleList[*(iPtr - 1)].getPosition(); Sim->dynamics.BCs().applyBC(currRelPos); relVecs.push_back(currRelPos + relVecs.back()); double mass = Sim->dynamics.getSpecies(Sim->particleList[*iPtr]).getMass(*iPtr); retVal.MassCentre += relVecs.back() * mass; totmass += mass; } retVal.MassCentre /= totmass; //Now determine the inertia tensor double data[NDIM * NDIM]; for (size_t i = 0; i < NDIM; i++) for (size_t j = i; j < NDIM; j++) data[i + j * NDIM] = 0.0; BOOST_FOREACH(Vector & vec, relVecs) { vec -= retVal.MassCentre; for (size_t i = 0; i < NDIM; i++) for (size_t j = i; j < NDIM; j++) data[i+j*NDIM] += vec[i] * vec[j]; }