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 OPCollMatrix::eventUpdate(const IntEvent& iEvent, const PairEventData&) { newEvent(iEvent.getParticle1ID(), iEvent.getType(), getClassKey(iEvent)); newEvent(iEvent.getParticle2ID(), iEvent.getType(), getClassKey(iEvent)); }
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)); }
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; }
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); }
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; }
bool Interaction::isInteraction(const IntEvent &coll) const { return isInteraction(Sim->particles[coll.getParticle1ID()], Sim->particles[coll.getParticle2ID()]); }
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; }
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 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; }