Example #1
0
  void NVE::moveA(){
    SimInfo::MoleculeIterator i;
    Molecule::IntegrableObjectIterator  j;
    Molecule* mol;
    StuntDouble* sd;
    Vector3d vel;
    Vector3d pos;
    Vector3d frc;
    Vector3d Tb;
    Vector3d ji;
    RealType mass;
    
    for (mol = info_->beginMolecule(i); mol != NULL; 
         mol = info_->nextMolecule(i)) {

      for (sd = mol->beginIntegrableObject(j); sd != NULL;
	   sd = mol->nextIntegrableObject(j)) {

	vel = sd->getVel();
	pos = sd->getPos();
	frc = sd->getFrc();
	mass = sd->getMass();
                
	// velocity half step
	vel += (dt2 /mass * PhysicalConstants::energyConvert) * frc;

	// position whole step
	pos += dt * vel;

	sd->setVel(vel);
	sd->setPos(pos);

	if (sd->isDirectional()){

	  // get and convert the torque to body frame

	  Tb = sd->lab2Body(sd->getTrq());

	  // get the angular momentum, and propagate a half step

	  ji = sd->getJ();

	  ji += (dt2  * PhysicalConstants::energyConvert) * Tb;

	  rotAlgo_->rotate(sd, ji, dt);

	  sd->setJ(ji);
	}

            
      }
    }
    flucQ_->moveA();
    rattle_->constraintA();    
  }    
Example #2
0
  Vector3d DensityPlot::calcNewOrigin() {

    int i;
    Vector3d newOrigin(0.0);
    RealType totalMass = 0.0;
    for (StuntDouble* sd = seleMan_.beginSelected(i); sd != NULL; sd = seleMan_.nextSelected(i)) {
      RealType mass = sd->getMass();
      totalMass += mass;
      newOrigin += sd->getPos() * mass;        
    }
    newOrigin /= totalMass;
    return newOrigin;
  }
Example #3
0
Vector3d Molecule::getComVel() {
    StuntDouble* sd;
    std::vector<StuntDouble*>::iterator i;
    Vector3d velCom;
    double totalMass = 0;
    double mass;
    
    for (sd = beginIntegrableObject(i); sd != NULL; sd = nextIntegrableObject(i)){
        mass = sd->getMass();
        totalMass += mass;
        velCom += sd->getVel() * mass;    
    }

    velCom /= totalMass;

    return velCom;
}
Example #4
0
  void NPT::moveB(void) {
    SimInfo::MoleculeIterator i;
    Molecule::IntegrableObjectIterator  j;
    Molecule* mol;
    StuntDouble* sd;
    int index;
    Vector3d Tb;
    Vector3d ji;
    Vector3d sc;
    Vector3d vel;
    Vector3d frc;
    RealType mass;

    thermostat = snap->getThermostat();
    RealType oldChi  = thermostat.first;
    RealType prevChi;

    loadEta();
    
    //save velocity and angular momentum
    index = 0;
    for (mol = info_->beginMolecule(i); mol != NULL; 
         mol = info_->nextMolecule(i)) {

      for (sd = mol->beginIntegrableObject(j); sd != NULL;
	   sd = mol->nextIntegrableObject(j)) {
                
	oldVel[index] = sd->getVel();

        if (sd->isDirectional())
	   oldJi[index] = sd->getJ();

	++index;
      }
    }

    // do the iteration:
    instaVol =thermo.getVolume();

    for(int k = 0; k < maxIterNum_; k++) {
      instaTemp =thermo.getTemperature();
      instaPress =thermo.getPressure();

      // evolve chi another half step using the temperature at t + dt/2
      prevChi = thermostat.first;
      thermostat.first = oldChi + dt2 * (instaTemp / targetTemp - 1.0) / tt2;

      //evolve eta
      this->evolveEtaB();
      this->calcVelScale();

      index = 0;
      for (mol = info_->beginMolecule(i); mol != NULL; 
           mol = info_->nextMolecule(i)) {

	for (sd = mol->beginIntegrableObject(j); sd != NULL;
	     sd = mol->nextIntegrableObject(j)) {            

	  frc = sd->getFrc();
	  mass = sd->getMass();

	  getVelScaleB(sc, index);

	  // velocity half step
	  vel = oldVel[index] 
            + dt2*PhysicalConstants::energyConvert/mass* frc 
            - dt2*sc;

	  sd->setVel(vel);

	  if (sd->isDirectional()) {
	    // get and convert the torque to body frame
	    Tb = sd->lab2Body(sd->getTrq());

	    ji = oldJi[index] 
              + dt2*PhysicalConstants::energyConvert*Tb 
              - dt2*thermostat.first*oldJi[index];

	    sd->setJ(ji);
	  }

	  ++index;
	}
      }
        
      rattle_->constraintB();

      if ((fabs(prevChi - thermostat.first) <= chiTolerance) && 
          this->etaConverged())
	break;
    }

    //calculate integral of chidt
    thermostat.second += dt2 * thermostat.first;

    snap->setThermostat(thermostat);

    flucQ_->moveB();
    saveEta();
  }
Example #5
0
  void NPT::moveA() {
    SimInfo::MoleculeIterator i;
    Molecule::IntegrableObjectIterator  j;
    Molecule* mol;
    StuntDouble* sd;
    Vector3d Tb, ji;
    RealType mass;
    Vector3d vel;
    Vector3d pos;
    Vector3d frc;
    Vector3d sc;
    int index;

    thermostat = snap->getThermostat();
    loadEta();
    
    instaTemp =thermo.getTemperature();
    press = thermo.getPressureTensor();
    instaPress = PhysicalConstants::pressureConvert* (press(0, 0) + press(1, 1) + press(2, 2)) / 3.0;
    instaVol =thermo.getVolume();

    Vector3d  COM = thermo.getCom();

    //evolve velocity half step

    calcVelScale();

    for (mol = info_->beginMolecule(i); mol != NULL; 
         mol = info_->nextMolecule(i)) {

      for (sd = mol->beginIntegrableObject(j); sd != NULL;
	   sd = mol->nextIntegrableObject(j)) {
                
	vel = sd->getVel();
	frc = sd->getFrc();

	mass = sd->getMass();

	getVelScaleA(sc, vel);

	// velocity half step  (use chi from previous step here):

	vel += dt2*PhysicalConstants::energyConvert/mass* frc - dt2*sc;
	sd->setVel(vel);

	if (sd->isDirectional()) {

	  // get and convert the torque to body frame

	  Tb = sd->lab2Body(sd->getTrq());

	  // get the angular momentum, and propagate a half step

	  ji = sd->getJ();

	  ji += dt2*PhysicalConstants::energyConvert * Tb 
            - dt2*thermostat.first* ji;
                
	  rotAlgo_->rotate(sd, ji, dt);

	  sd->setJ(ji);
	}
            
      }
    }
    // evolve chi and eta  half step

    thermostat.first += dt2 * (instaTemp / targetTemp - 1.0) / tt2;
    
    evolveEtaA();

    //calculate the integral of chidt
    thermostat.second += dt2 * thermostat.first;
    
    flucQ_->moveA();


    index = 0;
    for (mol = info_->beginMolecule(i); mol != NULL; 
         mol = info_->nextMolecule(i)) {

      for (sd = mol->beginIntegrableObject(j); sd != NULL;
	   sd = mol->nextIntegrableObject(j)) {

	oldPos[index++] = sd->getPos();            

      }
    }
    
    //the first estimation of r(t+dt) is equal to  r(t)

    for(int k = 0; k < maxIterNum_; k++) {
      index = 0;
      for (mol = info_->beginMolecule(i); mol != NULL; 
           mol = info_->nextMolecule(i)) {

	for (sd = mol->beginIntegrableObject(j); sd != NULL;
	     sd = mol->nextIntegrableObject(j)) {

	  vel = sd->getVel();
	  pos = sd->getPos();

	  this->getPosScale(pos, COM, index, sc);

	  pos = oldPos[index] + dt * (vel + sc);
	  sd->setPos(pos);     

	  ++index;
	}
      }

      rattle_->constraintA();
    }

    // Scale the box after all the positions have been moved:

    this->scaleSimBox();

    snap->setThermostat(thermostat);

    saveEta();
  }
Example #6
0
  void ContactAngle1::doFrame(int frame) {
    StuntDouble* sd;
    int i;
    
    if (evaluator1_.isDynamic()) {
      seleMan1_.setSelectionSet(evaluator1_.evaluate());
    }
    
    
    RealType mtot = 0.0;
    Vector3d com(V3Zero);
    RealType mass;
    
    for (sd = seleMan1_.beginSelected(i); sd != NULL;
         sd = seleMan1_.nextSelected(i)) {      
      mass = sd->getMass();
      mtot += mass;
      com += sd->getPos() * mass;
    }
    
    com /= mtot;

    RealType dz = com.z() - solidZ_;

    if (dz < 0.0) {
      sprintf(painCave.errMsg, 
              "ContactAngle1: Z-center of mass of selection, %lf, was\n"
              "\tlocated below the solid reference plane, %lf\n",
              com.z(), solidZ_);
      painCave.isFatal = 1;
      painCave.severity = OPENMD_ERROR;
      simError();
    }

    if (dz > dropletRadius_) {
      values_.push_back(180.0);
    } else {
    
      RealType k = pow(2.0, -4.0/3.0) * dropletRadius_;
      
      RealType z2 = dz*dz;
      RealType z3 = z2 * dz;
      RealType k2 = k*k;
      RealType k3 = k2*k;
      
      Polynomial<RealType> poly;
      poly.setCoefficient(4,      z3 +      k3);
      poly.setCoefficient(3,  8.0*z3 +  8.0*k3);
      poly.setCoefficient(2, 24.0*z3 + 18.0*k3);
      poly.setCoefficient(1, 32.0*z3          );
      poly.setCoefficient(0, 16.0*z3 - 27.0*k3);
      vector<RealType> realRoots = poly.FindRealRoots();

      RealType ct;
      
      vector<RealType>::iterator ri;


      RealType maxct = -1.0;
      for (ri = realRoots.begin(); ri !=realRoots.end(); ++ri) {
        ct = *ri;
        if (ct > 1.0)  ct = 1.0;
        if (ct < -1.0) ct = -1.0;

        // use the largest magnitude of ct that it finds:
        if (ct > maxct) {
          maxct = ct;
        }                  
      }
      
      values_.push_back( acos(maxct)*(180.0/M_PI) );
    }
  }    
Example #7
0
  void ContactAngle2::doFrame(int frame) {
    StuntDouble* sd;
    int i;

    // set up the bins for density analysis

    Mat3x3d hmat = info_->getSnapshotManager()->getCurrentSnapshot()->getHmat();
    RealType len = std::min(hmat(0, 0), hmat(1, 1));
    RealType zLen = hmat(2,2);

    RealType dr = len / (RealType) nRBins_;
    RealType dz = zLen / (RealType) nZBins_;

    std::vector<std::vector<RealType> > histo;
    histo.resize(nRBins_);
    for (unsigned int i = 0; i < histo.size(); ++i){
      histo[i].resize(nZBins_);
      std::fill(histo[i].begin(), histo[i].end(), 0.0);
    }      
        
    if (evaluator1_.isDynamic()) {
      seleMan1_.setSelectionSet(evaluator1_.evaluate());
    }
    
    Vector3d com(centroidX_, centroidY_, solidZ_);

    // now that we have the centroid, we can make cylindrical density maps
    Vector3d pos;
    RealType r;
    RealType z;
    
    for (sd = seleMan1_.beginSelected(i); sd != NULL;
         sd = seleMan1_.nextSelected(i)) {      
      pos = sd->getPos() - com;

      // r goes from zero upwards
      r = sqrt(pow(pos.x(), 2) + pow(pos.y(), 2));
      // z is possibly symmetric around 0
      z = pos.z();
          
      int whichRBin = int(r / dr);
      int whichZBin = int( (zLen/2.0 + z) / dz);
      
      if ((whichRBin < int(nRBins_)) && (whichZBin >= 0)
          && (whichZBin < int(nZBins_))) {
        histo[whichRBin][whichZBin] += sd->getMass();
      }
      
    }
    
    for(unsigned int i = 0 ; i < histo.size(); ++i){

      RealType rL = i * dr;
      RealType rU = rL + dr;
      RealType volSlice = NumericConstant::PI * dz * (( rU*rU ) - ( rL*rL ));

      for (unsigned int j = 0; j < histo[i].size(); ++j) {
        histo[i][j] *= PhysicalConstants::densityConvert / volSlice;
      }
    }

    std::vector<Vector<RealType, 2> > points;
    points.clear();
    
    for (unsigned int j = 0; j < nZBins_;  ++j) {

      // The z coordinates were measured relative to the selection
      // center of mass.  However, we're interested in the elevation
      // above the solid surface.  Also, the binning was done around
      // zero with enough bins to cover the zLength of the box:
      
      RealType thez =  com.z() - solidZ_  - zLen/2.0 + dz * (j + 0.5);
      bool aboveThresh = false;
      bool foundThresh = false;
      int rloc = 0;
      
      for (std::size_t i = 0; i < nRBins_;  ++i) {

        if (histo[i][j] >= threshDens_) aboveThresh = true;

        if (aboveThresh && (histo[i][j] <= threshDens_)) {
          rloc = i;
          foundThresh = true;
          aboveThresh = false;
        }

      }
      if (foundThresh) {
        Vector<RealType,2> point;
        point[0] = dr*(rloc+0.5);
        point[1] = thez;

        if (thez > bufferLength_) {
          points.push_back( point );
        }
      }      
    }

    int numPoints = points.size();

    // Compute the average of the data points.
    Vector<RealType, 2> average = points[0];
    int i0;
    for (i0 = 1; i0 < numPoints; ++i0) {
      average += points[i0];
    }
    RealType invNumPoints = ((RealType)1)/(RealType)numPoints;
    average *= invNumPoints;
    
    DynamicRectMatrix<RealType> mat(4, 4);
    int row, col;
    for (row = 0; row < 4; ++row) {
      for (col = 0; col < 4; ++col){
        mat(row,col) = 0.0;        
      }
    }
    for (int i = 0; i < numPoints; ++i) {
      RealType x = points[i][0];
      RealType y = points[i][1];
      RealType x2 = x*x;
      RealType y2 = y*y;
      RealType xy = x*y;
      RealType r2 = x2+y2;
      RealType xr2 = x*r2;
      RealType yr2 = y*r2;
      RealType r4 = r2*r2;

      mat(0,1) += x;
      mat(0,2) += y;
      mat(0,3) += r2;
      mat(1,1) += x2;
      mat(1,2) += xy;
      mat(1,3) += xr2;
      mat(2,2) += y2;
      mat(2,3) += yr2;
      mat(3,3) += r4;
    }
    mat(0,0) = (RealType)numPoints;

    for (row = 0; row < 4; ++row) {
      for (col = 0; col < row; ++col) {
        mat(row,col) = mat(col,row);
      }
    }

    for (row = 0; row < 4; ++row) {
      for (col = 0; col < 4; ++col) {
        mat(row,col) *= invNumPoints;
      }
    }

    JAMA::Eigenvalue<RealType> eigensystem(mat);
    DynamicRectMatrix<RealType> evects(4, 4);
    DynamicVector<RealType> evals(4);

    eigensystem.getRealEigenvalues(evals);
    eigensystem.getV(evects);

    DynamicVector<RealType> evector = evects.getColumn(0);
    RealType inv = ((RealType)1)/evector[3];  // beware zero divide
    RealType coeff[3];
    for (row = 0; row < 3; ++row) {
      coeff[row] = inv*evector[row];
    }

    Vector<RealType, 2> center;
    
    center[0] = -((RealType)0.5)*coeff[1];
    center[1] = -((RealType)0.5)*coeff[2];
    RealType radius = sqrt(fabs(center[0]*center[0] + center[1]*center[1]
                                - coeff[0]));

    int i1;
    for (i1 = 0; i1 < 100; ++i1) {
      // Update the iterates.
      Vector<RealType, 2> current = center;
      
      // Compute average L, dL/da, dL/db.
      RealType lenAverage = (RealType)0;
      Vector<RealType, 2> derLenAverage = Vector<RealType, 2>(0.0);
      for (i0 = 0; i0 < numPoints; ++i0) {
        Vector<RealType, 2> diff = points[i0] - center;
        RealType length = diff.length();
        if (length > 1e-6) {
          lenAverage += length;
          RealType invLength = ((RealType)1)/length;
          derLenAverage -= invLength*diff;
        }
      }
      lenAverage *= invNumPoints;
      derLenAverage *= invNumPoints;

      center = average + lenAverage*derLenAverage;
      radius = lenAverage;

      Vector<RealType, 2> diff = center - current;
      if (fabs(diff[0]) <= 1e-6 &&  fabs(diff[1]) <= 1e-6) {
        break;
      }
    }

    RealType zCen = center[1];
    RealType rDrop = radius;
    RealType ca;

    if (fabs(zCen) > rDrop) {
      ca = 180.0;
    } else {
      ca = 90.0 + asin(zCen/rDrop)*(180.0/M_PI);
    }

    values_.push_back( ca );    
  }