NEventData SysRescale::runEvent() { ++Sim->eventCount; const double currentkT(Sim->dynamics->getkT() / Sim->units.unitEnergy()); dout << "Rescaling kT " << currentkT << " To " << _kT / Sim->units.unitEnergy() << std::endl; NEventData SDat; for (const shared_ptr<Species>& species : Sim->species) for (const unsigned long& partID : *species->getRange()) SDat.L1partChanges.push_back(ParticleEventData(Sim->particles[partID], *species, RESCALE)); Sim->dynamics->updateAllParticles(); Sim->dynamics->rescaleSystemKineticEnergy(_kT / currentkT); //We must set the centre of mass velocity back to zero (assuming //this is the target velocity), otherwise it will drift with the //rescaling process Sim->setCOMVelocity(); RealTime += (Sim->systemTime - LastTime) / std::exp(0.5 * scaleFactor); LastTime = Sim->systemTime; scaleFactor += std::log(currentkT); dt = _timestep; return SDat; }
NEventData DynGravity::enforceParabola(Particle& part) const { updateParticle(part); const Species& species = *Sim->species(part); NEventData retval(ParticleEventData(part, species, VIRTUAL)); Vector pos(part.getPosition()), vel(part.getVelocity()); Sim->BCs->applyBC(pos, vel); //Find the dimension that is closest to size_t dim = NDIM; double time = std::numeric_limits<float>::infinity(); for (size_t iDim(0); iDim < NDIM; ++iDim) if (g[iDim] != 0) { double tmpTime = std::abs(- vel[iDim] / g[iDim]); if ((std::abs(tmpTime) < time)) { time = tmpTime; dim = iDim; } } #ifdef DYNAMO_DEBUG if (dim >= NDIM) M_throw() << "Could not find a dimension to enforce the parabola in!"; #endif part.getVelocity()[dim] = 0; return retval; }
void GVolumetricPotential::runEvent(Particle& part, const double dt) { //Despite the system not being streamed this must be done. This is //because the scheduler and all interactions, locals and systems //expect the particle to be up to date. Sim->dynamics->updateParticle(part); const size_t oldCellIndex = _cellData.getCellID(part.getID()); const int cellDirectionInt(Sim->dynamics->getSquareCellCollision3(part, calcPosition(oldCellIndex, part), _cellDimension)); const size_t cellDirection = abs(cellDirectionInt) - 1; GlobalEvent iEvent(getEvent(part)); #ifdef DYNAMO_DEBUG if (std::isnan(iEvent.getdt())) M_throw() << "A NAN Interaction collision time has been found when recalculating this global" << iEvent.stringData(Sim); #endif Sim->systemTime += iEvent.getdt(); Sim->ptrScheduler->stream(iEvent.getdt()); Sim->stream(iEvent.getdt()); //Calculate which cell the particle might end up in const auto oldCellCoord = _ordering.toCoord(oldCellIndex); auto newCellCoord = oldCellCoord; newCellCoord[cellDirection] += _ordering.getDimensions()[cellDirection] + ((cellDirectionInt > 0) ? 1 : -1); newCellCoord[cellDirection] %= _ordering.getDimensions()[cellDirection]; const size_t newCellIndex = _ordering.toIndex(newCellCoord); Vector vNorm{0,0,0}; vNorm[cellDirection] = (cellDirectionInt > 0) ? -1 : 1; NEventData EDat; //Run the collision and catch the data Sim->dynamics->updateParticle(part); Vector pos(part.getPosition()), vel(part.getVelocity()); Sim->BCs->applyBC(pos, vel); double potEnergyChange = 0.5 * (double(_volumeData[newCellIndex]) - double(_volumeData[oldCellIndex])); double arg = vel[cellDirection] * vel[cellDirection] - 2 * potEnergyChange / Sim->species(part)->getMass(part); if (arg > 0) { EDat = ParticleEventData(part, *Sim->species(part), WALL); part.getVelocity()[cellDirection] *= std::sqrt(arg) / std::abs(part.getVelocity()[cellDirection]); _cellData.moveTo(oldCellIndex, newCellIndex, part.getID()); } else EDat = Sim->dynamics->runPlaneEvent(part, vNorm, 1.0, 0.0); //Now we're past the event update the scheduler and plugins Sim->_sigParticleUpdate(EDat); Sim->ptrScheduler->fullUpdate(part); for (shared_ptr<OutputPlugin> & Ptr : Sim->outputPlugins) Ptr->eventUpdate(iEvent, EDat); }
void SysRescale::runEvent() const { double locdt = dt; Sim->systemTime += locdt; Sim->ptrScheduler->stream(locdt); //dynamics must be updated first Sim->stream(locdt); ++Sim->eventCount; double currentkT(Sim->dynamics->getkT() / Sim->units.unitEnergy()); dout << "Rescaling kT " << currentkT << " To " << _kT / Sim->units.unitEnergy() << std::endl; NEventData SDat; for (const shared_ptr<Species>& species : Sim->species) for (const unsigned long& partID : *species->getRange()) SDat.L1partChanges.push_back(ParticleEventData(Sim->particles[partID], *species, RESCALE)); Sim->dynamics->updateAllParticles(); Sim->dynamics->rescaleSystemKineticEnergy(_kT / currentkT); RealTime += (Sim->systemTime - LastTime) / std::exp(0.5 * scaleFactor); LastTime = Sim->systemTime; scaleFactor += std::log(currentkT); (*Sim->_sigParticleUpdate)(SDat); //Only 1ParticleEvents occur for (const ParticleEventData& PDat : SDat.L1partChanges) Sim->ptrScheduler->fullUpdate(Sim->particles[PDat.getParticleID()]); for (shared_ptr<OutputPlugin>& Ptr : Sim->outputPlugins) Ptr->eventUpdate(*this, SDat, locdt); for (shared_ptr<OutputPlugin>& Ptr : Sim->outputPlugins) Ptr->temperatureRescale(1.0/currentkT); dt = _timestep; Sim->ptrScheduler->rebuildList(); }
void GParabolaSentinel::runEvent(const Particle& part, const double) const { Sim->dynamics.getLiouvillean().updateParticle(part); GlobalEvent iEvent(getEvent(part)); if (iEvent.getdt() == HUGE_VAL) { //We've numerically drifted slightly passed the parabola, so //just reschedule the particles events, no need to enforce anything Sim->ptrScheduler->fullUpdate(part); return; } #ifdef DYNAMO_DEBUG if (boost::math::isnan(iEvent.getdt())) M_throw() << "A NAN Interaction collision time has been found when recalculating this global" << iEvent.stringData(Sim); #endif Sim->dSysTime += iEvent.getdt(); Sim->ptrScheduler->stream(iEvent.getdt()); Sim->dynamics.stream(iEvent.getdt()); Sim->dynamics.getLiouvillean().enforceParabola(part); #ifdef DYNAMO_DEBUG iEvent.addTime(Sim->freestreamAcc); Sim->freestreamAcc = 0; NEventData EDat(ParticleEventData(part, Sim->dynamics.getSpecies(part), VIRTUAL)); Sim->signalParticleUpdate(EDat); BOOST_FOREACH(std::tr1::shared_ptr<OutputPlugin> & Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, EDat); #else Sim->freestreamAcc += iEvent.getdt(); #endif Sim->ptrScheduler->fullUpdate(part); }
void GPBCSentinel::runEvent(Particle& part, const double dt) const { GlobalEvent iEvent(part, dt, VIRTUAL, *this); Sim->systemTime += iEvent.getdt(); Sim->ptrScheduler->stream(iEvent.getdt()); Sim->stream(iEvent.getdt()); NEventData EDat(ParticleEventData(part, *Sim->species[part], VIRTUAL)); Sim->signalParticleUpdate(EDat); BOOST_FOREACH(shared_ptr<OutputPlugin> & Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, EDat); Sim->ptrScheduler->fullUpdate(part); }
void GFrancesco::runEvent(Particle& part, const double) { const double dt = _eventTimes[part] - Sim->systemTime; _eventTimes[part] = HUGE_VAL; Event iEvent(part, dt, GLOBAL, GAUSSIAN, ID); Sim->systemTime += dt; Sim->ptrScheduler->stream(dt); Sim->stream(dt); Sim->dynamics->updateParticle(part); NEventData EDat(ParticleEventData(part, *Sim->species(part), GAUSSIAN)); //Kill the rotational motion Sim->dynamics->getRotData(part).angularVelocity = Vector{0,0,0}; //Reassign the linear motion part.getVelocity() = _vel * (Sim->dynamics->getRotData(part).orientation * magnet::math::Quaternion::initialDirector()); Sim->_sigParticleUpdate(EDat); for (shared_ptr<OutputPlugin> & Ptr : Sim->outputPlugins) Ptr->eventUpdate(iEvent, EDat); Sim->ptrScheduler->fullUpdate(part); }