OPRGyration::molGyrationDat OPRGyration::getGyrationEigenSystem(const shared_ptr<IDRange>& range, const dynamo::Simulation* Sim) { //Determine the centre of mass. Watch for periodic images Vector tmpVec; molGyrationDat retVal; retVal.MassCentre = Vector{0,0,0}; double totmass = Sim->species[Sim->particles[*(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 (IDRange::iterator iPtr = range->begin()+1; iPtr != range->end(); iPtr++) { Vector currRelPos = Sim->particles[*iPtr].getPosition() - Sim->particles[*(iPtr - 1)].getPosition(); Sim->BCs->applyBC(currRelPos); relVecs.push_back(currRelPos + relVecs.back()); double mass = Sim->species[Sim->particles[*iPtr]]->getMass(*iPtr); retVal.MassCentre += relVecs.back() * mass; totmass += mass; } retVal.MassCentre /= totmass; //Now determine the inertia tensor Matrix inertiaTensor; for (Vector& vec : relVecs) { vec -= retVal.MassCentre; inertiaTensor += Dyadic(vec, vec); } std::pair<std::array<Vector, 3>, std::array<double, 3> > result = magnet::math::symmetric_eigen_decomposition(inertiaTensor); for (size_t i = 0; i < NDIM; i++) { retVal.EigenVal[i] = result.second[i] / range->size(); //EigenVec Components for (size_t j = 0; j < NDIM; j++) retVal.EigenVec[i][j] = result.first[i][j]; } retVal.MassCentre += Sim->particles[*(range->begin())].getPosition(); return retVal; }
OPRGyration::molGyrationDat OPRGyration::getGyrationEigenSystem(const shared_ptr<IDRange>& range, const dynamo::Simulation* Sim) { //Determine the centre of mass. Watch for periodic images Vector tmpVec; molGyrationDat retVal; retVal.MassCentre = Vector{0,0,0}; double totmass = Sim->species(Sim->particles[*(range->begin())])->getMass(*(range->begin())); //Walk along the chain Vector origin_position = Vector{0,0,0}; Matrix inertiaTensor; for (IDRange::iterator iPtr = range->begin()+1; iPtr != range->end(); iPtr++) { Vector currRelPos = Sim->particles[*iPtr].getPosition() - Sim->particles[*(iPtr - 1)].getPosition(); Sim->BCs->applyBC(currRelPos); const Vector unfolded_pos = currRelPos + origin_position; const double mass = Sim->species(Sim->particles[*iPtr])->getMass(*iPtr); retVal.MassCentre += origin_position * mass; inertiaTensor += mass * ((unfolded_pos * unfolded_pos) * Matrix::identity() - Dyadic(unfolded_pos, unfolded_pos)); totmass += mass; origin_position = unfolded_pos; } retVal.MassCentre /= totmass; retVal.MassCentre += Sim->particles[*(range->begin())].getPosition(); std::pair<std::array<Vector, 3>, std::array<double, 3> > result = magnet::math::symmetric_eigen_decomposition(inertiaTensor / totmass); for (size_t i = 0; i < NDIM; i++) { retVal.EigenVal[i] = result.second[i] / range->size(); //EigenVec Components for (size_t j = 0; j < NDIM; j++) retVal.EigenVec[i][j] = result.first[i][j]; } return retVal; }
OPRGyration::molGyrationDat OPRGyration::getGyrationEigenSystem(const shared_ptr<IDRange>& range, const dynamo::Simulation* Sim) { //Determine the centre of mass. Watch for periodic images Vector tmpVec; molGyrationDat retVal; retVal.MassCentre = Vector (0,0,0); double totmass = Sim->species[Sim->particles[*(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 (IDRange::iterator iPtr = range->begin()+1; iPtr != range->end(); iPtr++) { Vector currRelPos = Sim->particles[*iPtr].getPosition() - Sim->particles[*(iPtr - 1)].getPosition(); Sim->BCs->applyBC(currRelPos); relVecs.push_back(currRelPos + relVecs.back()); double mass = Sim->species[Sim->particles[*iPtr]]->getMass(*iPtr); retVal.MassCentre += relVecs.back() * mass; totmass += mass; } retVal.MassCentre /= totmass; //Now determine the inertia tensor Matrix inertiaTensor; inertiaTensor.zero(); BOOST_FOREACH(Vector & vec, relVecs) { vec -= retVal.MassCentre; inertiaTensor += Dyadic(vec, vec); }
void OPMisc::initialise() { _KE.init(Sim->dynamics->getSystemKineticEnergy()); _internalE.init(Sim->calcInternalEnergy()); dout << "Particle Count " << Sim->N << "\nSim Unit Length " << Sim->units.unitLength() << "\nSim Unit Time " << Sim->units.unitTime() << "\nDensity " << Sim->getNumberDensity() * Sim->units.unitVolume() << "\nPacking Fraction " << Sim->getPackingFraction() << "\nTemperature " << getCurrentkT() / Sim->units.unitEnergy() << "\nNo. of Species " << Sim->species.size() << "\nSimulation box length <x y z> < "; for (size_t iDim = 0; iDim < NDIM; iDim++) dout << Sim->primaryCellSize[iDim] / Sim->units.unitLength() << " "; dout << ">\n"; Matrix kineticP; Vector thermalConductivityFS(0,0,0); _speciesMomenta.clear(); _speciesMomenta.resize(Sim->species.size()); _speciesMasses.clear(); _speciesMasses.resize(Sim->species.size()); BOOST_FOREACH(const Particle& part, Sim->particles) { const Species& sp = *(Sim->species[part]); const double mass = sp.getMass(part.getID()); kineticP += mass * Dyadic(part.getVelocity(), part.getVelocity()); _speciesMasses[sp.getID()] += mass; _speciesMomenta[sp.getID()] += mass * part.getVelocity(); thermalConductivityFS += part.getVelocity() * Sim->dynamics->getParticleKineticEnergy(part); } Vector sysMomentum(0,0,0); _systemMass = 0; for (size_t i(0); i < Sim->species.size(); ++i) { sysMomentum += _speciesMomenta[i]; _systemMass += _speciesMasses[i]; } _kineticP.init(kineticP); _sysMomentum.init(sysMomentum); //Set up the correlators double correlator_dt = Sim->lastRunMFT / 8; if (correlator_dt == 0.0) correlator_dt = 1.0 / sqrt(getCurrentkT()); _thermalConductivity.resize(correlator_dt, 10); _thermalConductivity.setFreeStreamValue(thermalConductivityFS); _viscosity.resize(correlator_dt, 10); _viscosity.setFreeStreamValue(kineticP); _thermalDiffusion.resize(Sim->species.size()); _mutualDiffusion.resize(Sim->species.size() * Sim->species.size()); for (size_t spid1(0); spid1 < Sim->species.size(); ++spid1) { _thermalDiffusion[spid1].resize(correlator_dt, 10); _thermalDiffusion[spid1] .setFreeStreamValue(thermalConductivityFS, _speciesMomenta[spid1] - (_speciesMasses[spid1] / _systemMass) * _sysMomentum.current()); for (size_t spid2(spid1); spid2 < Sim->species.size(); ++spid2) { _mutualDiffusion[spid1 * Sim->species.size() + spid2].resize(correlator_dt, 10); _mutualDiffusion[spid1 * Sim->species.size() + spid2].setFreeStreamValue (_speciesMomenta[spid1] - (_speciesMasses[spid1] / _systemMass) * _sysMomentum.current(), _speciesMomenta[spid2] - (_speciesMasses[spid2] / _systemMass) * _sysMomentum.current()); } } dout << "Total momentum < "; for (size_t iDim = 0; iDim < NDIM; iDim++) dout << _sysMomentum.current()[iDim] / Sim->units.unitMomentum() << " "; dout << ">\n"; std::time(&tstartTime); clock_gettime(CLOCK_MONOTONIC, &acc_tstartTime); std::string sTime(std::ctime(&tstartTime)); sTime[sTime.size()-1] = ' '; dout << "Started on " << sTime << std::endl; }
void OPMisc::eventUpdate(const NEventData& NDat) { Vector thermalDel(0,0,0); BOOST_FOREACH(const ParticleEventData& PDat, NDat.L1partChanges) { const Particle& part = Sim->particles[PDat.getParticleID()]; const double p1E = Sim->dynamics->getParticleKineticEnergy(Sim->particles[PDat.getParticleID()]); const Species& species = *Sim->species[PDat.getSpeciesID()]; double mass = species.getMass(part.getID()); Vector delP1 = mass * (part.getVelocity() - PDat.getOldVel()); _singleEvents += (PDat.getType() != VIRTUAL); _virtualEvents += (PDat.getType() == VIRTUAL); _KE += PDat.getDeltaKE(); _internalE += PDat.getDeltaU(); _kineticP += mass * (Dyadic(part.getVelocity(), part.getVelocity()) - Dyadic(PDat.getOldVel(), PDat.getOldVel())); _sysMomentum += delP1; _speciesMomenta[species.getID()] += delP1; thermalDel += part.getVelocity() * p1E - PDat.getOldVel() * (p1E - PDat.getDeltaKE()); } BOOST_FOREACH(const PairEventData& PDat, NDat.L2partChanges) { _KE += PDat.particle1_.getDeltaKE() + PDat.particle2_.getDeltaKE(); _internalE += PDat.particle1_.getDeltaU() + PDat.particle2_.getDeltaU(); _dualEvents += (PDat.getType() != VIRTUAL); _virtualEvents += (PDat.getType() == VIRTUAL); const Particle& part1 = Sim->particles[PDat.particle1_.getParticleID()]; const Particle& part2 = Sim->particles[PDat.particle2_.getParticleID()]; const Species& sp1 = *Sim->species[PDat.particle1_.getSpeciesID()]; const Species& sp2 = *Sim->species[PDat.particle2_.getSpeciesID()]; const double p1E = Sim->dynamics->getParticleKineticEnergy(part1); const double p2E = Sim->dynamics->getParticleKineticEnergy(part2); const double mass1 = sp1.getMass(part1.getID()); const double mass2 = sp2.getMass(part2.getID()); Vector delP = mass1 * (part1.getVelocity() - PDat.particle1_.getOldVel()); collisionalP += magnet::math::Dyadic(PDat.rij, delP); _kineticP += mass1 * (Dyadic(part1.getVelocity(), part1.getVelocity()) - Dyadic(PDat.particle1_.getOldVel(), PDat.particle1_.getOldVel())) + mass2 * (Dyadic(part2.getVelocity(), part2.getVelocity()) - Dyadic(PDat.particle2_.getOldVel(), PDat.particle2_.getOldVel())); _viscosity.addImpulse(magnet::math::Dyadic(PDat.rij, delP)); _speciesMomenta[sp1.getID()] += delP; _speciesMomenta[sp2.getID()] -= delP; Vector thermalImpulse = PDat.rij * PDat.particle1_.getDeltaKE(); _thermalConductivity.addImpulse(thermalImpulse); for (size_t spid1(0); spid1 < Sim->species.size(); ++spid1) _thermalDiffusion[spid1].addImpulse(thermalImpulse, Vector(0,0,0)); thermalDel += part1.getVelocity() * p1E + part2.getVelocity() * p2E - PDat.particle1_.getOldVel() * (p1E - PDat.particle1_.getDeltaKE()) - PDat.particle2_.getOldVel() * (p2E - PDat.particle2_.getDeltaKE()); } _thermalConductivity.setFreeStreamValue (_thermalConductivity.getFreeStreamValue() + thermalDel); _viscosity.setFreeStreamValue(_kineticP.current()); for (size_t spid1(0); spid1 < Sim->species.size(); ++spid1) { _thermalDiffusion[spid1] .setFreeStreamValue(_thermalConductivity.getFreeStreamValue(), _speciesMomenta[spid1] - _sysMomentum.current() * (_speciesMasses[spid1] / _systemMass)); for (size_t spid2(spid1); spid2 < Sim->species.size(); ++spid2) _mutualDiffusion[spid1 * Sim->species.size() + spid2].setFreeStreamValue (_speciesMomenta[spid1] - (_speciesMasses[spid1] / _systemMass) * _sysMomentum.current(), _speciesMomenta[spid2] - (_speciesMasses[spid2] / _systemMass) * _sysMomentum.current()); } }