PairEventData DynCompression::SmoothSpheresColl(const IntEvent& event, const double& e, const double& d2, const EEventType& eType) const { Particle& particle1 = Sim->particles[event.getParticle1ID()]; Particle& particle2 = Sim->particles[event.getParticle2ID()]; updateParticlePair(particle1, particle2); PairEventData retVal(particle1, particle2, *Sim->species[particle1], *Sim->species[particle2], eType); Sim->BCs->applyBC(retVal.rij, retVal.vijold); double p1Mass = Sim->species[retVal.particle1_.getSpeciesID()]->getMass(particle1.getID()); double p2Mass = Sim->species[retVal.particle2_.getSpeciesID()]->getMass(particle2.getID()); double r2 = retVal.rij.nrm2(); retVal.rvdot = (retVal.rij | retVal.vijold); double mu = 1.0 / ((1.0 / p1Mass) + (1.0 / p2Mass)); bool infinite_masses = (p1Mass == HUGE_VAL) && (p2Mass == HUGE_VAL); if (infinite_masses) { p1Mass = p2Mass = 1; mu = 0.5; } retVal.impulse = retVal.rij * ((1.0 + e) * mu * (retVal.rvdot - growthRate * sqrt(d2 * r2)) / retVal.rij.nrm2()); particle1.getVelocity() -= retVal.impulse / p1Mass; particle2.getVelocity() += retVal.impulse / p2Mass; //If both particles have infinite mass we pretend no momentum was transferred retVal.impulse *= !infinite_masses; return retVal; }
void OPMisc::eventUpdate(const IntEvent& eevent, const PairEventData& PDat) { stream(eevent.getdt()); eventUpdate(PDat); newEvent(eevent.getParticle1ID(), eevent.getType(), getClassKey(eevent)); newEvent(eevent.getParticle2ID(), eevent.getType(), getClassKey(eevent)); }
void OPCollMatrix::eventUpdate(const IntEvent& iEvent, const PairEventData&) { newEvent(iEvent.getParticle1ID(), iEvent.getType(), getClassKey(iEvent)); newEvent(iEvent.getParticle2ID(), iEvent.getType(), getClassKey(iEvent)); }
void ILines::runEvent(Particle& p1, Particle& p2, const IntEvent& iEvent) { PairEventData retval; switch (iEvent.getType()) { case CORE: { ++Sim->eventCount; //We have a line interaction! Run it double e = (_e->getProperty(p1.getID()) + _e->getProperty(p2.getID())) * 0.5; double l = (_length->getProperty(p1.getID()) + _length->getProperty(p2.getID())) * 0.5; retval = Sim->dynamics->runLineLineCollision(iEvent, e, l); break; } case NBHOOD_IN: { ICapture::add(p1, p2); retval = PairEventData(p1, p2, *Sim->species[p1], *Sim->species[p2], VIRTUAL); iEvent.setType(VIRTUAL); break; } case NBHOOD_OUT: { ICapture::remove(p1, p2); retval = PairEventData(p1, p2, *Sim->species[p1], *Sim->species[p2], VIRTUAL); iEvent.setType(VIRTUAL); break; } case VIRTUAL: { retval = PairEventData(p1, p2, *Sim->species[p1], *Sim->species[p2], VIRTUAL); iEvent.setType(VIRTUAL); break; } default: M_throw() << "Unknown collision type"; } Sim->_sigParticleUpdate(retval); Sim->ptrScheduler->fullUpdate(p1, p2); for (shared_ptr<OutputPlugin> & Ptr : Sim->outputPlugins) Ptr->eventUpdate(iEvent, retval); }
void OPCollTicker::eventUpdate(const IntEvent &event, const PairEventData &) { stream(event.getdt()); ticker(); }
void OPViscosityE::eventUpdate(const IntEvent& iEvent, const PairEventData& PDat) { stream(iEvent.getdt()); impulseDelG(PDat); updateConstDelG(PDat); }
void OPRijVij::eventUpdate(const IntEvent& iEvent, const PairEventData& pDat) { process2PED(rvdotacc[mapKey(iEvent.getType(), getClassKey(iEvent))], pDat); }
PairEventData DynNewtonian::parallelCubeColl(const IntEvent& event, const double& e, const double&, const EEventType& eType) const { Particle& particle1 = Sim->particles[event.getParticle1ID()]; Particle& particle2 = Sim->particles[event.getParticle2ID()]; updateParticlePair(particle1, particle2); PairEventData retVal(particle1, particle2, *Sim->species[particle1], *Sim->species[particle2], eType); Sim->BCs->applyBC(retVal.rij, retVal.vijold); size_t dim(0); for (size_t iDim(1); iDim < NDIM; ++iDim) if (fabs(retVal.rij[dim]) < fabs(retVal.rij[iDim])) dim = iDim; double p1Mass = Sim->species[retVal.particle1_.getSpeciesID()]->getMass(particle1.getID()); double p2Mass = Sim->species[retVal.particle2_.getSpeciesID()]->getMass(particle2.getID()); double mu = p1Mass * p2Mass/ (p1Mass + p2Mass); Vector collvec(0,0,0); if (retVal.rij[dim] < 0) collvec[dim] = -1; else collvec[dim] = 1; retVal.rvdot = (retVal.rij | retVal.vijold); retVal.dP = collvec * (1.0 + e) * mu * (collvec | retVal.vijold); //This function must edit particles so it overrides the const! particle1.getVelocity() -= retVal.dP / p1Mass; particle2.getVelocity() += retVal.dP / p2Mass; retVal.particle1_.setDeltaKE(0.5 * p1Mass * (particle1.getVelocity().nrm2() - retVal.particle1_.getOldVel().nrm2())); retVal.particle2_.setDeltaKE(0.5 * p2Mass * (particle2.getVelocity().nrm2() - retVal.particle2_.getOldVel().nrm2())); return retVal; }
void ISWSequence::runEvent(Particle& p1, Particle& p2, const IntEvent& iEvent) { ++Sim->eventCount; const double e = (_e->getProperty(p1.getID()) + _e->getProperty(p2.getID())) * 0.5; const double d = (_diameter->getProperty(p1.getID()) + _diameter->getProperty(p2.getID())) * 0.5; const double d2 = d * d; const double l = (_lambda->getProperty(p1.getID()) + _lambda->getProperty(p2.getID())) * 0.5; const double ld2 = d * l * d * l; const double pairenergy = alphabet[sequence[p1.getID() % sequence.size()]][sequence[p2.getID() % sequence.size()]] * _unitEnergy->getMaxValue(); switch (iEvent.getType()) { case CORE: { PairEventData retVal(Sim->dynamics->SmoothSpheresColl(iEvent, e, d2, CORE)); Sim->_sigParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); for (shared_ptr<OutputPlugin> & Ptr : Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } case STEP_IN: { PairEventData retVal(Sim->dynamics->SphereWellEvent(iEvent, pairenergy, ld2, 1)); if (retVal.getType() != BOUNCE) ICapture::add(p1, p2); Sim->_sigParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); for (shared_ptr<OutputPlugin> & Ptr : Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } case STEP_OUT: { PairEventData retVal(Sim->dynamics->SphereWellEvent(iEvent, -pairenergy, ld2, 0)); if (retVal.getType() != BOUNCE) ICapture::remove(p1, p2); Sim->_sigParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); for (shared_ptr<OutputPlugin> & Ptr : Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } default: M_throw() << "Unknown collision type"; } }
void OPThermalDiffusionE::eventUpdate(const IntEvent& iEvent, const PairEventData& PDat) { stream(iEvent.getdt()); delG += impulseDelG(PDat); updateConstDelG(PDat); }
void OPThermalConductivitySpeciesSpeciesE::eventUpdate(const IntEvent& iEvent, const PairEventData& PDat) { stream(iEvent.getdt()); //impulseDelG(PDat); updateConstDelG(PDat); }
PairEventData DynGravity::SmoothSpheresColl(const IntEvent& event, const double& ne, const double& d2, const EEventType& eType) const { Particle& particle1 = Sim->particles[event.getParticle1ID()]; Particle& particle2 = Sim->particles[event.getParticle2ID()]; updateParticlePair(particle1, particle2); Vector rij = particle1.getPosition() - particle2.getPosition(), vij = particle1.getVelocity() - particle2.getVelocity(); Sim->BCs->applyBC(rij, vij); //Check if two particles are collapsing //First, the elastic V calculation double vnrm = std::fabs((rij | vij) / rij.nrm()); double e = ne; if (vnrm < elasticV) e = 1.0; //Check if a particle is collapsing on a static particle if (!particle1.testState(Particle::DYNAMIC) || !particle2.testState(Particle::DYNAMIC)) { double gnrm = g.nrm(); if (gnrm > 0) if (std::fabs((vij | g) / gnrm) < elasticV) e = 1.0; } //Now the tc model; if (_tc > 0) { if ((Sim->systemTime - _tcList[particle1.getID()] < _tc) || (Sim->systemTime - _tcList[particle2.getID()] < _tc)) e = 1.0; _tcList[particle1.getID()] = Sim->systemTime; _tcList[particle2.getID()] = Sim->systemTime; } return DynNewtonian::SmoothSpheresColl(event, e, d2, eType); }
void ISoftCore::runEvent(const Particle& p1, const Particle& p2, const IntEvent& iEvent) const { ++Sim->eventCount; double d2 = (_diameter->getProperty(p1.getID()) + _diameter->getProperty(p2.getID())) * 0.5; d2 *= d2; double wd = (_wellDepth->getProperty(p1.getID()) + _wellDepth->getProperty(p2.getID())) * 0.5; switch (iEvent.getType()) { case WELL_IN: { PairEventData retVal(Sim->dynamics.getLiouvillean() .SphereWellEvent(iEvent, wd, d2)); if (retVal.getType() != BOUNCE) addToCaptureMap(p1, p2); //Now we're past the event, update the scheduler and plugins Sim->signalParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); BOOST_FOREACH(magnet::ClonePtr<OutputPlugin> & Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } case WELL_OUT: { PairEventData retVal(Sim->dynamics.getLiouvillean() .SphereWellEvent(iEvent, -wd, d2)); if (retVal.getType() != BOUNCE) removeFromCaptureMap(p1, p2); Sim->signalParticleUpdate(retVal); //Now we're past the event, update the scheduler and plugins Sim->ptrScheduler->fullUpdate(p1, p2); BOOST_FOREACH(magnet::ClonePtr<OutputPlugin>& Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } default: M_throw() << "Unknown collision type"; } }
PairEventData ILines::runEvent(Particle& p1, Particle& p2, const IntEvent& iEvent) { PairEventData retval; switch (iEvent.getType()) { case CORE: { ++Sim->eventCount; //We have a line interaction! Run it const double e = _e->getProperty(p1, p2); const double l = _length->getProperty(p1, p2); retval = Sim->dynamics->runLineLineCollision(iEvent, e, l); break; } case NBHOOD_IN: { ICapture::add(p1, p2); retval = PairEventData(p1, p2, *Sim->species(p1), *Sim->species(p2), VIRTUAL); iEvent.setType(VIRTUAL); break; } case NBHOOD_OUT: { ICapture::remove(p1, p2); retval = PairEventData(p1, p2, *Sim->species(p1), *Sim->species(p2), VIRTUAL); iEvent.setType(VIRTUAL); break; } case VIRTUAL: { retval = PairEventData(p1, p2, *Sim->species(p1), *Sim->species(p2), VIRTUAL); iEvent.setType(VIRTUAL); break; } default: M_throw() << "Unknown collision type"; } return retval; }
void ISquareWell::runEvent(Particle& p1, Particle& p2, const IntEvent& iEvent) { ++Sim->eventCount; double d = (_diameter->getProperty(p1.getID()) + _diameter->getProperty(p2.getID())) * 0.5; double d2 = d * d; double e = (_e->getProperty(p1.getID()) + _e->getProperty(p2.getID())) * 0.5; double l = (_lambda->getProperty(p1.getID()) + _lambda->getProperty(p2.getID())) * 0.5; double ld2 = d * l * d * l; double wd = (_wellDepth->getProperty(p1.getID()) + _wellDepth->getProperty(p2.getID())) * 0.5; switch (iEvent.getType()) { case CORE: { PairEventData retVal(Sim->dynamics->SmoothSpheresColl(iEvent, e, d2, CORE)); Sim->_sigParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); for (shared_ptr<OutputPlugin> & Ptr : Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } case STEP_IN: { PairEventData retVal(Sim->dynamics->SphereWellEvent(iEvent, wd, ld2, 1)); if (retVal.getType() != BOUNCE) ICapture::add(p1, p2); Sim->ptrScheduler->fullUpdate(p1, p2); Sim->_sigParticleUpdate(retVal); for (shared_ptr<OutputPlugin> & Ptr : Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } case STEP_OUT: { PairEventData retVal(Sim->dynamics->SphereWellEvent(iEvent, -wd, ld2, 0)); if (retVal.getType() != BOUNCE) ICapture::remove(p1, p2); Sim->_sigParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); for (shared_ptr<OutputPlugin> & Ptr : Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } default: M_throw() << "Unknown collision type"; } }
void OPVACF::eventUpdate(const IntEvent& iEvent, const PairEventData& PDat) { //Move the time forward currentdt += iEvent.getdt(); //Now test if we've gone over the step time while (currentdt >= dt) { currentdt -= dt; newG(PDat); } }
void OPCubeComp::eventUpdate(const IntEvent& iEvent, const PairEventData& pDat) { mapdata& ref = angles[mapKey(iEvent.getType(), getClassKey(iEvent))]; std::vector<double> vals(NDIM, 0); for (size_t i(0); i < NDIM; ++i) vals[i] = pDat.rij[i] * pDat.rij[i] / Sim->dynamics.units().unitArea(); std::sort(vals.begin(), vals.end()); for (size_t i(0); i < NDIM; ++i) ref.angles[i].addVal(vals[i]); }
void IStepped::runEvent(Particle& p1, Particle& p2, const IntEvent& iEvent) { ++Sim->eventCount; const double length_scale = 0.5 * (_lengthScale->getProperty(p1.getID()) + _lengthScale->getProperty(p2.getID())); const double energy_scale = 0.5 * (_energyScale->getProperty(p1.getID()) + _energyScale->getProperty(p2.getID())); ICapture::const_iterator capstat = ICapture::find(ICapture::key_type(p1, p2)); const size_t old_step_ID = (capstat == ICapture::end()) ? 0 : capstat->second; const std::pair<double, double> step_bounds = _potential->getStepBounds(old_step_ID); size_t new_step_ID; size_t edge_ID; double diameter; switch (iEvent.getType()) { case STEP_OUT: { new_step_ID = _potential->outer_step_ID(old_step_ID); edge_ID = _potential->outer_edge_ID(old_step_ID); diameter = step_bounds.second * length_scale; break; } case STEP_IN: { new_step_ID = _potential->inner_step_ID(old_step_ID); edge_ID = _potential->inner_edge_ID(old_step_ID); diameter = step_bounds.first * length_scale; break; } default: M_throw() << "Unknown event type"; } PairEventData retVal = Sim->dynamics->SphereWellEvent(iEvent, _potential->getEnergyChange(new_step_ID, old_step_ID) * energy_scale, diameter * diameter, new_step_ID); EdgeData& data = _edgedata[std::pair<size_t, EEventType>(edge_ID, retVal.getType())]; ++data.counter; data.rdotv_sum += retVal.rvdot; //Check if the particles changed their step ID if (retVal.getType() != BOUNCE) ICapture::operator[](ICapture::key_type(p1, p2)) = new_step_ID; Sim->_sigParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); for (shared_ptr<OutputPlugin> & Ptr : Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); }
void ISWSequence::runEvent(const Particle& p1, const Particle& p2, const IntEvent& iEvent) const { ++Sim->eventCount; double e = (_e->getProperty(p1.getID()) + _e->getProperty(p2.getID())) * 0.5; double d = (_diameter->getProperty(p1.getID()) + _diameter->getProperty(p2.getID())) * 0.5; double d2 = d * d; double l = (_lambda->getProperty(p1.getID()) + _lambda->getProperty(p2.getID())) * 0.5; double ld2 = d * l * d * l; switch (iEvent.getType()) { case CORE: { PairEventData retVal(Sim->dynamics.getLiouvillean().SmoothSpheresColl(iEvent, e, d2, CORE)); Sim->signalParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); BOOST_FOREACH(std::tr1::shared_ptr<OutputPlugin> & Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } case WELL_IN: { PairEventData retVal(Sim->dynamics.getLiouvillean() .SphereWellEvent (iEvent, alphabet [sequence[p1.getID() % sequence.size()]] [sequence[p2.getID() % sequence.size()]] * _unitEnergy->getMaxValue(), ld2)); if (retVal.getType() != BOUNCE) addToCaptureMap(p1, p2); Sim->signalParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); BOOST_FOREACH(std::tr1::shared_ptr<OutputPlugin> & Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } case WELL_OUT: { PairEventData retVal(Sim->dynamics.getLiouvillean() .SphereWellEvent (iEvent, -alphabet [sequence[p1.getID() % sequence.size()]] [sequence[p2.getID() % sequence.size()]] * _unitEnergy->getMaxValue(), ld2)); if (retVal.getType() != BOUNCE) removeFromCaptureMap(p1, p2); Sim->signalParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); BOOST_FOREACH(std::tr1::shared_ptr<OutputPlugin> & Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } default: M_throw() << "Unknown collision type"; } }
PairEventData DynNewtonianMCCMap::SphereWellEvent(const IntEvent& event, const double& deltaKE, const double &, size_t newstate) const { Particle& particle1 = Sim->particles[event.getParticle1ID()]; Particle& particle2 = Sim->particles[event.getParticle2ID()]; updateParticlePair(particle1, particle2); PairEventData retVal(particle1, particle2, *Sim->species(particle1), *Sim->species(particle2), event.getType()); Sim->BCs->applyBC(retVal.rij,retVal.vijold); retVal.rvdot = (retVal.rij | retVal.vijold); double p1Mass = Sim->species[retVal.particle1_.getSpeciesID()]->getMass(particle1); double p2Mass = Sim->species[retVal.particle2_.getSpeciesID()]->getMass(particle2); double mu = p1Mass * p2Mass / (p1Mass + p2Mass); double R2 = retVal.rij.nrm2(); //Calculate the deformed energy change of the system (the one used in the dynamics) double MCDeltaKE = deltaKE; //If there are entries for the current and possible future energy, then take them into account detail::CaptureMap contact_map = *_interaction; //Add the current bias potential MCDeltaKE += W(contact_map) * Sim->ensemble->getEnsembleVals()[2]; //subtract the possible bias potential in the new state contact_map[detail::CaptureMap::key_type(particle1, particle2)] = newstate; MCDeltaKE -= W(contact_map) * Sim->ensemble->getEnsembleVals()[2]; //Test if the deformed energy change allows a capture event to occur double sqrtArg = retVal.rvdot * retVal.rvdot + 2.0 * R2 * MCDeltaKE / mu; if ((MCDeltaKE < 0) && (sqrtArg < 0)) { event.setType(BOUNCE); retVal.setType(BOUNCE); retVal.impulse = retVal.rij * 2.0 * mu * retVal.rvdot / R2; } else { retVal.particle1_.setDeltaU(-0.5 * deltaKE); retVal.particle2_.setDeltaU(-0.5 * deltaKE); if (retVal.rvdot < 0) retVal.impulse = retVal.rij * (2.0 * MCDeltaKE / (std::sqrt(sqrtArg) - retVal.rvdot)); else retVal.impulse = retVal.rij * (-2.0 * MCDeltaKE / (retVal.rvdot + std::sqrt(sqrtArg))); } #ifdef DYNAMO_DEBUG if (std::isnan(retVal.impulse[0])) M_throw() << "A nan dp has ocurred"; #endif //This function must edit particles so it overrides the const! particle1.getVelocity() -= retVal.impulse / p1Mass; particle2.getVelocity() += retVal.impulse / p2Mass; return retVal; }
void OPIntEnergyHist::eventUpdate(const IntEvent &event, const PairEventData &) { intEnergyHist.addVal(_ptrOPMisc->getConfigurationalU(), event.getdt()); }
PairEventData DynCompression::SphereWellEvent(const IntEvent& event, const double& deltaKE, const double& d2, size_t) const { Particle& particle1 = Sim->particles[event.getParticle1ID()]; Particle& particle2 = Sim->particles[event.getParticle2ID()]; updateParticlePair(particle1, particle2); PairEventData retVal(particle1, particle2, *Sim->species[particle1], *Sim->species[particle2], event.getType()); Sim->BCs->applyBC(retVal.rij, retVal.vijold); double p1Mass = Sim->species[retVal.particle1_.getSpeciesID()]->getMass(particle1.getID()); double p2Mass = Sim->species[retVal.particle2_.getSpeciesID()]->getMass(particle2.getID()); double mu = 1.0 / ((1.0 / p1Mass) + (1.0 / p2Mass)); bool infinite_masses = (p1Mass == HUGE_VAL) && (p2Mass == HUGE_VAL); if (infinite_masses) { p1Mass = p2Mass = 1; mu = 0.5; } Vector urij = retVal.rij / retVal.rij.nrm(); retVal.rvdot = (urij | retVal.vijold); double sqrtArg = std::pow(retVal.rvdot - growthRate * sqrt(d2), 2) + (2.0 * deltaKE / mu); if ((deltaKE < 0) && (sqrtArg < 0)) { event.setType(BOUNCE); retVal.setType(BOUNCE); retVal.impulse = urij * (2.0 * mu * (retVal.rvdot - growthRate * sqrt(d2))); } else if (deltaKE==0) retVal.impulse = Vector(0,0,0); else { retVal.particle1_.setDeltaU(-0.5 * deltaKE); retVal.particle2_.setDeltaU(-0.5 * deltaKE); if (retVal.rvdot < 0) retVal.impulse = urij * (2.0 * deltaKE / (growthRate * sqrt(d2) + std::sqrt(sqrtArg) - retVal.rvdot )); else retVal.impulse = urij * (2.0 * deltaKE / (growthRate * sqrt(d2) - std::sqrt(sqrtArg) - retVal.rvdot )); ; } retVal.rvdot *= retVal.rij.nrm(); #ifdef DYNAMO_DEBUG if (std::isnan(retVal.impulse[0])) M_throw() << "A nan dp has ocurred" << "\ndeltaKE = " << deltaKE << "\ngrowthRate = " << growthRate << "\nd2 = " << d2 << "\nsqrtArg = " << sqrtArg << "\nrvdot = " << retVal.rvdot << "\nArg " << (growthRate * sqrt(d2) - std::sqrt(sqrtArg) - retVal.rvdot) ; #endif particle1.getVelocity() -= retVal.impulse / p1Mass; particle2.getVelocity() += retVal.impulse / p2Mass; retVal.impulse *= !infinite_masses; return retVal; }
bool Interaction::isInteraction(const IntEvent &coll) const { return isInteraction(Sim->particles[coll.getParticle1ID()], Sim->particles[coll.getParticle2ID()]); }
classKey getClassKey(const IntEvent& i) { return classKey(i.getInteractionID(), INTERACTION); }
PairEventData DynNewtonianMC::SphereWellEvent(const IntEvent& event, const double& deltaKE, const double &, size_t) const { Particle& particle1 = Sim->particles[event.getParticle1ID()]; Particle& particle2 = Sim->particles[event.getParticle2ID()]; updateParticlePair(particle1, particle2); PairEventData retVal(particle1, particle2, *Sim->species[particle1], *Sim->species[particle2], event.getType()); Sim->BCs->applyBC(retVal.rij,retVal.vijold); retVal.rvdot = (retVal.rij | retVal.vijold); double p1Mass = Sim->species[retVal.particle1_.getSpeciesID()]->getMass(particle1.getID()); double p2Mass = Sim->species[retVal.particle2_.getSpeciesID()]->getMass(particle2.getID()); double mu = p1Mass * p2Mass / (p1Mass + p2Mass); double R2 = retVal.rij.nrm2(); double CurrentE = Sim->getOutputPlugin<OPMisc>()->getConfigurationalU(); //Calculate the deformed energy change of the system (the one used in the dynamics) double MCDeltaKE = deltaKE; //If there are entries for the current and possible future energy, then take them into account MCDeltaKE += W(CurrentE) * Sim->ensemble->getEnsembleVals()[2]; MCDeltaKE -= W(CurrentE - deltaKE) * Sim->ensemble->getEnsembleVals()[2]; //Test if the deformed energy change allows a capture event to occur double sqrtArg = retVal.rvdot * retVal.rvdot + 2.0 * R2 * MCDeltaKE / mu; if ((MCDeltaKE < 0) && (sqrtArg < 0)) { event.setType(BOUNCE); retVal.setType(BOUNCE); retVal.impulse = retVal.rij * 2.0 * mu * retVal.rvdot / R2; } else { retVal.particle1_.setDeltaU(-0.5 * deltaKE); retVal.particle2_.setDeltaU(-0.5 * deltaKE); if (retVal.rvdot < 0) retVal.impulse = retVal.rij * (2.0 * MCDeltaKE / (std::sqrt(sqrtArg) - retVal.rvdot)); else retVal.impulse = retVal.rij * (-2.0 * MCDeltaKE / (retVal.rvdot + std::sqrt(sqrtArg))); } #ifdef DYNAMO_DEBUG if (boost::math::isnan(retVal.impulse[0])) M_throw() << "A nan dp has ocurred"; #endif //This function must edit particles so it overrides the const! particle1.getVelocity() -= retVal.impulse / p1Mass; particle2.getVelocity() += retVal.impulse / p2Mass; return retVal; }
PairEventData DynNewtonian::SmoothSpheresColl(const IntEvent& event, const double& e, const double&, const EEventType& eType) const { Particle& particle1 = Sim->particles[event.getParticle1ID()]; Particle& particle2 = Sim->particles[event.getParticle2ID()]; updateParticlePair(particle1, particle2); PairEventData retVal(particle1, particle2, *Sim->species[particle1], *Sim->species[particle2], eType); Sim->BCs->applyBC(retVal.rij, retVal.vijold); double p1Mass = Sim->species[retVal.particle1_.getSpeciesID()]->getMass(particle1.getID()); double p2Mass = Sim->species[retVal.particle2_.getSpeciesID()]->getMass(particle2.getID()); retVal.rvdot = (retVal.rij | retVal.vijold); //Treat special cases if one particle has infinite mass if ((p1Mass == 0) && (p2Mass != 0)) //if (!particle1.testState(Particle::DYNAMIC) && particle2.testState(Particle::DYNAMIC)) { retVal.dP = p2Mass * retVal.rij * ((1.0 + e) * retVal.rvdot / retVal.rij.nrm2()); //This function must edit particles so it overrides the const! particle2.getVelocity() += retVal.dP / p2Mass; } else if ((p1Mass != 0) && (p2Mass == 0)) //if (particle1.testState(Particle::DYNAMIC) && !particle2.testState(Particle::DYNAMIC)) { retVal.dP = p1Mass * retVal.rij * ((1.0 + e) * retVal.rvdot / retVal.rij.nrm2()); //This function must edit particles so it overrides the const! particle1.getVelocity() -= retVal.dP / p1Mass; } else { bool isInfInf = (p1Mass == 0) && (p2Mass == 0); //If both particles have infinite mass we just collide them as identical masses if (isInfInf) p1Mass = p2Mass = 1; double mu = p1Mass * p2Mass / (p1Mass + p2Mass); retVal.dP = retVal.rij * ((1.0 + e) * mu * retVal.rvdot / retVal.rij.nrm2()); //This function must edit particles so it overrides the const! particle1.getVelocity() -= retVal.dP / p1Mass; particle2.getVelocity() += retVal.dP / p2Mass; //If both particles have infinite mass we pretend no momentum was transferred retVal.dP *= !isInfInf; } retVal.particle1_.setDeltaKE(0.5 * p1Mass * (particle1.getVelocity().nrm2() - retVal.particle1_.getOldVel().nrm2())); retVal.particle2_.setDeltaKE(0.5 * p2Mass * (particle2.getVelocity().nrm2() - retVal.particle2_.getOldVel().nrm2())); lastCollParticle1 = particle1.getID(); lastCollParticle2 = particle2.getID(); lastAbsoluteClock = Sim->systemTime; return retVal; }
void IDumbbells::runEvent(const Particle& p1, const Particle& p2, const IntEvent& iEvent) const { double d = (_diameter->getProperty(p1.getID()) + _diameter->getProperty(p2.getID())) * 0.5; double l = (_length->getProperty(p1.getID()) + _length->getProperty(p2.getID())) * 0.5; double e = (_e->getProperty(p1.getID()) + _e->getProperty(p2.getID())) * 0.5; switch (iEvent.getType()) { case CORE: { ++Sim->eventCount; //We have a line interaction! Run it PairEventData retval(Sim->dynamics.getLiouvillean() .runOffCenterSphereOffCenterSphereCollision (iEvent, e, l, d)); Sim->signalParticleUpdate(retval); Sim->ptrScheduler->fullUpdate(p1, p2); BOOST_FOREACH(std::tr1::shared_ptr<OutputPlugin> & Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, retval); break; } case WELL_IN: { addToCaptureMap(p1, p2); //Unfortunately we cannot be smart as this well event may have //been pushed into both particles update lists, therefore we //must do a full update Sim->ptrScheduler->fullUpdate(p1, p2); Sim->freestreamAcc += iEvent.getdt(); break; } case WELL_OUT: { removeFromCaptureMap(p1, p2); //Unfortunately we cannot be smart as this well event may have //been pushed into both particles update lists, therefore we //must do a full update Sim->ptrScheduler->fullUpdate(p1, p2); Sim->freestreamAcc += iEvent.getdt(); break; } default: M_throw() << "Unknown collision type"; } }
void IStepped::runEvent(const Particle& p1, const Particle& p2, const IntEvent& iEvent) const { ++Sim->eventCount; switch (iEvent.getType()) { case WELL_OUT: { cmap_it capstat = getCMap_it(p1,p2); double d = steps[capstat->second-1].first * _unitLength->getMaxValue(); double d2 = d * d; double dE = steps[capstat->second-1].second; if (capstat->second > 1) dE -= steps[capstat->second - 2].second; dE *= _unitEnergy->getMaxValue(); PairEventData retVal(Sim->dynamics.getLiouvillean().SphereWellEvent (iEvent, dE, d2)); if (retVal.getType() != BOUNCE) if (!(--capstat->second)) //capstat is zero so delete captureMap.erase(capstat); Sim->signalParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); BOOST_FOREACH(magnet::ClonePtr<OutputPlugin> & Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } case WELL_IN: { cmap_it capstat = getCMap_it(p1, p2); if (capstat == captureMap.end()) capstat = captureMap.insert (captureMapType::value_type ((p1.getID() < p2.getID()) ? cMapKey(p1.getID(), p2.getID()) : cMapKey(p2.getID(), p1.getID()), 0)).first; double d = steps[capstat->second].first * _unitLength->getMaxValue(); double d2 = d * d; double dE = steps[capstat->second].second; if (capstat->second > 0) dE -= steps[capstat->second - 1].second; dE *= _unitEnergy->getMaxValue(); PairEventData retVal = Sim->dynamics.getLiouvillean().SphereWellEvent(iEvent, -dE, d2); if (retVal.getType() != BOUNCE) ++(capstat->second); else if (!capstat->second) captureMap.erase(capstat); Sim->signalParticleUpdate(retVal); Sim->ptrScheduler->fullUpdate(p1, p2); BOOST_FOREACH(magnet::ClonePtr<OutputPlugin> & Ptr, Sim->outputPlugins) Ptr->eventUpdate(iEvent, retVal); break; } default: M_throw() << "Unknown collision type"; } }
bool System::operator<(const IntEvent& iEvent) const { return dt < iEvent.getdt(); }