예제 #1
0
ParticleEventData
DynNewtonian::randomGaussianEvent(Particle& part, const double& sqrtT,
                                  const size_t dimensions) const
{
#ifdef DYNAMO_DEBUG
    if (dimensions > NDIM)
        M_throw() << "Number of dimensions passed larger than NDIM!";
#endif

    //See http://mathworld.wolfram.com/SpherePointPicking.html

    if (hasOrientationData())
        M_throw() << "Need to implement thermostating of the rotational degrees"
                  " of freedom";

    //Ensure the particle is free streamed first
    updateParticle(part);

    //Collect the precoll data
    ParticleEventData tmpDat(part, *Sim->species[part], GAUSSIAN);

    double mass = Sim->species[tmpDat.getSpeciesID()]->getMass(part.getID());
    double factor = sqrtT / std::sqrt(mass);

    //Assign the new velocities
    for (size_t iDim = 0; iDim < dimensions; iDim++)
        part.getVelocity()[iDim] = Sim->normal_sampler() * factor;

    tmpDat.setDeltaKE(0.5 * mass * (part.getVelocity().nrm2() - tmpDat.getOldVel().nrm2()));

    return tmpDat;
}
예제 #2
0
ParticleEventData
DynNewtonian::runAndersenWallCollision(Particle& part, const Vector & vNorm, const double& sqrtT, const double) const
{
    updateParticle(part);

    if (hasOrientationData())
        M_throw() << "Need to implement thermostating of the rotational degrees"
                  " of freedom";

    //This gives a completely new random unit vector with a properly
    //distributed Normal component. See Granular Simulation Book
    ParticleEventData tmpDat(part, *Sim->species[part], WALL);

    double mass = Sim->species[tmpDat.getSpeciesID()]->getMass(part.getID());

    for (size_t iDim = 0; iDim < NDIM; iDim++)
        part.getVelocity()[iDim] = Sim->normal_sampler() * sqrtT / std::sqrt(mass);

    part.getVelocity()
    //This first line adds a component in the direction of the normal
    += vNorm * (sqrtT * sqrt(-2.0*log(1.0-Sim->uniform_sampler()) / mass)
                //This removes the original normal component
                -(part.getVelocity() | vNorm));

    tmpDat.setDeltaKE(0.5 * mass * (part.getVelocity().nrm2() - tmpDat.getOldVel().nrm2()));

    return tmpDat;
}
예제 #3
0
  ParticleEventData 
  DynCompression::runAndersenWallCollision(Particle& part, const Vector & vNorm, const double& sqrtT, const double d) const
  {  
    updateParticle(part);

    if (hasOrientationData())
      M_throw() << "Need to implement thermostating of the rotational degrees"
	" of freedom";

    //This gives a completely new random unit vector with a properly
    //distributed Normal component. See Granular Simulation Book
    ParticleEventData tmpDat(part, *Sim->species[part], WALL);
 
    double mass = Sim->species[tmpDat.getSpeciesID()]->getMass(part.getID());

    std::normal_distribution<> normal_dist;
    std::uniform_real_distribution<> uniform_dist;

    for (size_t iDim = 0; iDim < NDIM; iDim++)
      part.getVelocity()[iDim] = normal_dist(Sim->ranGenerator) * sqrtT / std::sqrt(mass);
  
    part.getVelocity()
      //This first line adds a component in the direction of the normal
      += vNorm * (sqrtT * sqrt(-2.0*log(1.0 - uniform_dist(Sim->ranGenerator)) / mass)
		  //This removes the original normal component
		  -(part.getVelocity() | vNorm)
		  //This adds on the velocity of the wall
		  + d * growthRate)
      ;

    return tmpDat; 
  }