예제 #1
0
  OPRGyration::molGyrationDat
  OPRGyration::getGyrationEigenSystem(const shared_ptr<IDRange>& range, const dynamo::Simulation* Sim)
  {
    //Determine the centre of mass. Watch for periodic images
    Vector  tmpVec;  
  
    molGyrationDat retVal;
    retVal.MassCentre = Vector{0,0,0};

    double totmass = Sim->species[Sim->particles[*(range->begin())]]->getMass(*(range->begin()));
    std::vector<Vector> relVecs;
    relVecs.reserve(range->size());
    relVecs.push_back(Vector{0,0,0});
  
    //Walk along the chain
    for (IDRange::iterator iPtr = range->begin()+1; iPtr != range->end(); iPtr++)
      {
	Vector currRelPos = Sim->particles[*iPtr].getPosition() 
	  - Sim->particles[*(iPtr - 1)].getPosition();

	Sim->BCs->applyBC(currRelPos);

	relVecs.push_back(currRelPos + relVecs.back());

	double mass = Sim->species[Sim->particles[*iPtr]]->getMass(*iPtr);

	retVal.MassCentre += relVecs.back() * mass;
	totmass += mass;
      }

    retVal.MassCentre /= totmass;

    //Now determine the inertia tensor
    Matrix inertiaTensor;

    for (Vector& vec : relVecs)
      {
	vec -= retVal.MassCentre;
	inertiaTensor += Dyadic(vec, vec);
      }

    std::pair<std::array<Vector, 3>, std::array<double, 3> > result
      = magnet::math::symmetric_eigen_decomposition(inertiaTensor);

    for (size_t i = 0; i < NDIM; i++)
      {	
	retVal.EigenVal[i] = result.second[i] / range->size();

	//EigenVec Components
	for (size_t j = 0; j < NDIM; j++)
	  retVal.EigenVec[i][j] = result.first[i][j];
      }

    retVal.MassCentre += Sim->particles[*(range->begin())].getPosition();

    return retVal;
  }
예제 #2
0
  OPRGyration::molGyrationDat
  OPRGyration::getGyrationEigenSystem(const shared_ptr<IDRange>& range, const dynamo::Simulation* Sim)
  {
    //Determine the centre of mass. Watch for periodic images
    Vector  tmpVec;  
  
    molGyrationDat retVal;
    retVal.MassCentre = Vector{0,0,0};

    double totmass = Sim->species(Sim->particles[*(range->begin())])->getMass(*(range->begin()));
    //Walk along the chain
    Vector origin_position = Vector{0,0,0};
    Matrix inertiaTensor;
    
    for (IDRange::iterator iPtr = range->begin()+1; iPtr != range->end(); iPtr++)
      {
	Vector currRelPos = Sim->particles[*iPtr].getPosition() - Sim->particles[*(iPtr - 1)].getPosition();
	Sim->BCs->applyBC(currRelPos);

	const Vector unfolded_pos = currRelPos + origin_position;

	const double mass = Sim->species(Sim->particles[*iPtr])->getMass(*iPtr);

	retVal.MassCentre += origin_position * mass;
	inertiaTensor += mass * ((unfolded_pos * unfolded_pos) * Matrix::identity() - Dyadic(unfolded_pos, unfolded_pos));
	totmass += mass;
	origin_position = unfolded_pos;
      }

    retVal.MassCentre /= totmass;
    retVal.MassCentre += Sim->particles[*(range->begin())].getPosition();
    
    std::pair<std::array<Vector, 3>, std::array<double, 3> > result
      = magnet::math::symmetric_eigen_decomposition(inertiaTensor / totmass);

    for (size_t i = 0; i < NDIM; i++)
      {	
	retVal.EigenVal[i] = result.second[i] / range->size();

	//EigenVec Components
	for (size_t j = 0; j < NDIM; j++)
	  retVal.EigenVec[i][j] = result.first[i][j];
      }
    return retVal;
  }
예제 #3
0
OPRGyration::molGyrationDat
OPRGyration::getGyrationEigenSystem(const shared_ptr<IDRange>& range, const dynamo::Simulation* Sim)
{
    //Determine the centre of mass. Watch for periodic images
    Vector  tmpVec;

    molGyrationDat retVal;
    retVal.MassCentre = Vector (0,0,0);

    double totmass = Sim->species[Sim->particles[*(range->begin())]]->getMass(*(range->begin()));
    std::vector<Vector> relVecs;
    relVecs.reserve(range->size());
    relVecs.push_back(Vector(0,0,0));

    //Walk along the chain
    for (IDRange::iterator iPtr = range->begin()+1; iPtr != range->end(); iPtr++)
    {
        Vector currRelPos = Sim->particles[*iPtr].getPosition()
                            - Sim->particles[*(iPtr - 1)].getPosition();

        Sim->BCs->applyBC(currRelPos);

        relVecs.push_back(currRelPos + relVecs.back());

        double mass = Sim->species[Sim->particles[*iPtr]]->getMass(*iPtr);

        retVal.MassCentre += relVecs.back() * mass;
        totmass += mass;
    }

    retVal.MassCentre /= totmass;

    //Now determine the inertia tensor
    Matrix inertiaTensor;
    inertiaTensor.zero();

    BOOST_FOREACH(Vector & vec, relVecs)
    {
        vec -= retVal.MassCentre;
        inertiaTensor += Dyadic(vec, vec);
    }
예제 #4
0
  void
  OPMisc::initialise()
  {
    _KE.init(Sim->dynamics->getSystemKineticEnergy());
    _internalE.init(Sim->calcInternalEnergy());

    dout << "Particle Count " << Sim->N
	 << "\nSim Unit Length " << Sim->units.unitLength()
	 << "\nSim Unit Time " << Sim->units.unitTime()
	 << "\nDensity " << Sim->getNumberDensity()
      * Sim->units.unitVolume()
	 << "\nPacking Fraction " << Sim->getPackingFraction()
	 << "\nTemperature " << getCurrentkT() / Sim->units.unitEnergy()
	 << "\nNo. of Species " << Sim->species.size()
	 << "\nSimulation box length <x y z> < ";
    for (size_t iDim = 0; iDim < NDIM; iDim++)
      dout  << Sim->primaryCellSize[iDim] / Sim->units.unitLength() << " ";
    dout << ">\n";

    Matrix kineticP;
    Vector thermalConductivityFS(0,0,0);
    _speciesMomenta.clear();
    _speciesMomenta.resize(Sim->species.size());
    _speciesMasses.clear();
    _speciesMasses.resize(Sim->species.size());

    BOOST_FOREACH(const Particle& part, Sim->particles)
      {
	const Species& sp = *(Sim->species[part]);
	const double mass = sp.getMass(part.getID());

	kineticP += mass * Dyadic(part.getVelocity(), part.getVelocity());
	_speciesMasses[sp.getID()] += mass;
	_speciesMomenta[sp.getID()] += mass * part.getVelocity();
	thermalConductivityFS 
	  += part.getVelocity() * Sim->dynamics->getParticleKineticEnergy(part);
      }

    Vector sysMomentum(0,0,0);
    _systemMass = 0;
    for (size_t i(0); i < Sim->species.size(); ++i)
      {
	sysMomentum += _speciesMomenta[i];
	_systemMass += _speciesMasses[i];
      }

    _kineticP.init(kineticP);
    _sysMomentum.init(sysMomentum);

    //Set up the correlators
    double correlator_dt = Sim->lastRunMFT / 8;
    if (correlator_dt == 0.0)
      correlator_dt = 1.0 / sqrt(getCurrentkT());

    _thermalConductivity.resize(correlator_dt, 10);
    _thermalConductivity.setFreeStreamValue(thermalConductivityFS);

    _viscosity.resize(correlator_dt, 10);
    _viscosity.setFreeStreamValue(kineticP);
    
    _thermalDiffusion.resize(Sim->species.size());
    _mutualDiffusion.resize(Sim->species.size() * Sim->species.size());
    for (size_t spid1(0); spid1 < Sim->species.size(); ++spid1)
      {
	_thermalDiffusion[spid1].resize(correlator_dt, 10);
	_thermalDiffusion[spid1]
	  .setFreeStreamValue(thermalConductivityFS,
			      _speciesMomenta[spid1]
			      - (_speciesMasses[spid1] / _systemMass)
			      * _sysMomentum.current());
	
	for (size_t spid2(spid1); spid2 < Sim->species.size(); ++spid2)
	  {
	    _mutualDiffusion[spid1 * Sim->species.size() + spid2].resize(correlator_dt, 10);
	    _mutualDiffusion[spid1 * Sim->species.size() + spid2].setFreeStreamValue
	      (_speciesMomenta[spid1] - (_speciesMasses[spid1] / _systemMass) * _sysMomentum.current(),
	       _speciesMomenta[spid2] - (_speciesMasses[spid2] / _systemMass) * _sysMomentum.current());
	  }
      }

    dout << "Total momentum < ";
    for (size_t iDim = 0; iDim < NDIM; iDim++)
      dout  << _sysMomentum.current()[iDim] / Sim->units.unitMomentum() << " ";
    dout << ">\n";

    std::time(&tstartTime);

    clock_gettime(CLOCK_MONOTONIC, &acc_tstartTime);

    std::string sTime(std::ctime(&tstartTime));
    sTime[sTime.size()-1] = ' ';

    dout << "Started on " << sTime << std::endl;
  }
예제 #5
0
  void OPMisc::eventUpdate(const NEventData& NDat)
  {
    Vector thermalDel(0,0,0);

    BOOST_FOREACH(const ParticleEventData& PDat, NDat.L1partChanges)
      {
	const Particle& part = Sim->particles[PDat.getParticleID()];
	const double p1E = Sim->dynamics->getParticleKineticEnergy(Sim->particles[PDat.getParticleID()]);
	const Species& species = *Sim->species[PDat.getSpeciesID()];
	double mass = species.getMass(part.getID());
	Vector delP1 = mass * (part.getVelocity() - PDat.getOldVel());

        _singleEvents += (PDat.getType() != VIRTUAL);
	_virtualEvents += (PDat.getType() == VIRTUAL);

	_KE += PDat.getDeltaKE();
	_internalE += PDat.getDeltaU();
	
	_kineticP += mass * (Dyadic(part.getVelocity(), part.getVelocity())
			     - Dyadic(PDat.getOldVel(), PDat.getOldVel()));

	_sysMomentum += delP1;
	_speciesMomenta[species.getID()] += delP1;

	thermalDel += part.getVelocity() * p1E
	  - PDat.getOldVel() * (p1E - PDat.getDeltaKE());
      }

    BOOST_FOREACH(const PairEventData& PDat, NDat.L2partChanges)
      {
	_KE += PDat.particle1_.getDeltaKE() + PDat.particle2_.getDeltaKE();
	_internalE += PDat.particle1_.getDeltaU() + PDat.particle2_.getDeltaU();

	_dualEvents += (PDat.getType() != VIRTUAL);
	_virtualEvents += (PDat.getType() == VIRTUAL);

	const Particle& part1 = Sim->particles[PDat.particle1_.getParticleID()];
	const Particle& part2 = Sim->particles[PDat.particle2_.getParticleID()];
	const Species& sp1 = *Sim->species[PDat.particle1_.getSpeciesID()];
	const Species& sp2 = *Sim->species[PDat.particle2_.getSpeciesID()];
	const double p1E = Sim->dynamics->getParticleKineticEnergy(part1);
	const double p2E = Sim->dynamics->getParticleKineticEnergy(part2);
	const double mass1 = sp1.getMass(part1.getID());
	const double mass2 = sp2.getMass(part2.getID());

	Vector delP = mass1 * (part1.getVelocity() - PDat.particle1_.getOldVel());

	collisionalP += magnet::math::Dyadic(PDat.rij, delP);

	_kineticP
	  += mass1 * (Dyadic(part1.getVelocity(), part1.getVelocity())
		      - Dyadic(PDat.particle1_.getOldVel(), PDat.particle1_.getOldVel()))
	  + mass2 * (Dyadic(part2.getVelocity(), part2.getVelocity())
		     - Dyadic(PDat.particle2_.getOldVel(), PDat.particle2_.getOldVel()));

	_viscosity.addImpulse(magnet::math::Dyadic(PDat.rij, delP));

	_speciesMomenta[sp1.getID()] += delP;
	_speciesMomenta[sp2.getID()] -= delP;

	Vector thermalImpulse = PDat.rij * PDat.particle1_.getDeltaKE();
	_thermalConductivity.addImpulse(thermalImpulse);
	for (size_t spid1(0); spid1 < Sim->species.size(); ++spid1)
	  _thermalDiffusion[spid1].addImpulse(thermalImpulse, Vector(0,0,0));

	thermalDel += part1.getVelocity() * p1E + part2.getVelocity() * p2E
	  - PDat.particle1_.getOldVel() * (p1E - PDat.particle1_.getDeltaKE())
	  - PDat.particle2_.getOldVel() * (p2E - PDat.particle2_.getDeltaKE());
      }

    _thermalConductivity.setFreeStreamValue
      (_thermalConductivity.getFreeStreamValue() + thermalDel);

    _viscosity.setFreeStreamValue(_kineticP.current());

    for (size_t spid1(0); spid1 < Sim->species.size(); ++spid1)
      {
	_thermalDiffusion[spid1]
	  .setFreeStreamValue(_thermalConductivity.getFreeStreamValue(),
			      _speciesMomenta[spid1] - _sysMomentum.current() * (_speciesMasses[spid1] / _systemMass));

	for (size_t spid2(spid1); spid2 < Sim->species.size(); ++spid2)
	  _mutualDiffusion[spid1 * Sim->species.size() + spid2].setFreeStreamValue
	    (_speciesMomenta[spid1] - (_speciesMasses[spid1] / _systemMass) * _sysMomentum.current(),
	     _speciesMomenta[spid2] - (_speciesMasses[spid2] / _systemMass) * _sysMomentum.current());
      }
  }