Пример #1
0
  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;
  }
Пример #2
0
  void 
  OPCollMatrix::eventUpdate(const IntEvent& iEvent, const PairEventData&)
  {
    newEvent(iEvent.getParticle1ID(), iEvent.getType(), 
	     getClassKey(iEvent));

    newEvent(iEvent.getParticle2ID(), iEvent.getType(), 
	     getClassKey(iEvent));
  }
Пример #3
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));
  }
Пример #4
0
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;
}
Пример #5
0
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;
  }
Пример #7
0
  bool 
  Interaction::isInteraction(const IntEvent &coll) const
  { 
    return isInteraction(Sim->particles[coll.getParticle1ID()],
			 Sim->particles[coll.getParticle2ID()]); 
  }
Пример #8
0
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;
}
Пример #9
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;
  }
Пример #10
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;
  }