Beispiel #1
0
  void 
  OPCollMatrix::eventUpdate(const IntEvent& iEvent, const PairEventData&)
  {
    newEvent(iEvent.getParticle1ID(), iEvent.getType(), 
	     getClassKey(iEvent));

    newEvent(iEvent.getParticle2ID(), iEvent.getType(), 
	     getClassKey(iEvent));
  }
Beispiel #2
0
void 
OPRijVij::eventUpdate(const IntEvent& iEvent, const PairEventData& pDat)
{
  
  process2PED(rvdotacc[mapKey(iEvent.getType(), 
			      getClassKey(iEvent))], pDat);
}
Beispiel #3
0
  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";
      }
  }
Beispiel #4
0
  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));
  }
Beispiel #5
0
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";
    }
}
Beispiel #6
0
  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";
      } 
  }
Beispiel #7
0
  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);
  }
Beispiel #8
0
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]);
}
Beispiel #9
0
  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);
  }
Beispiel #10
0
  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;
  }
Beispiel #11
0
  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;
  }
Beispiel #13
0
  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";
      }
  }
Beispiel #14
0
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";
    } 
}
Beispiel #15
0
  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;
  }
Beispiel #16
0
  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;
  }