void OPCollMatrix::eventUpdate(const IntEvent& iEvent, const PairEventData&) { newEvent(iEvent.getParticle1ID(), iEvent.getType(), getClassKey(iEvent)); newEvent(iEvent.getParticle2ID(), iEvent.getType(), getClassKey(iEvent)); }
void OPRijVij::eventUpdate(const IntEvent& iEvent, const PairEventData& pDat) { process2PED(rvdotacc[mapKey(iEvent.getType(), getClassKey(iEvent))], pDat); }
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 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 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"; } }
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 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 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); }
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 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 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"; } }
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; }