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(); }
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; }
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; }
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(); }
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(); }
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) ); } }
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 ); }