ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/rnemd/RNEMD.cpp
(Generate patch)

Comparing branches/development/src/rnemd/RNEMD.cpp (file contents):
Revision 1854 by gezelter, Thu Mar 28 20:54:06 2013 UTC vs.
Revision 1874 by gezelter, Wed May 15 15:09:35 2013 UTC

# Line 71 | Line 71 | namespace OpenMD {
71    RNEMD::RNEMD(SimInfo* info) : info_(info), evaluator_(info), seleMan_(info),
72                                  evaluatorA_(info), seleManA_(info),
73                                  commonA_(info), evaluatorB_(info),
74 <                                seleManB_(info), commonB_(info),
74 >                                seleManB_(info), commonB_(info),
75 >                                hasData_(false), hasDividingArea_(false),
76                                  usePeriodicBoundaryConditions_(info->getSimParams()->getUsePeriodicBoundaryConditions()) {
77  
78      trialCount_ = 0;
# Line 420 | Line 421 | namespace OpenMD {
421        data_[VELOCITY] = velocity;
422        outputMap_["VELOCITY"] = VELOCITY;
423  
424 +      OutputData angularVelocity;
425 +      angularVelocity.units = "angstroms^2/fs";
426 +      angularVelocity.title =  "AngularVelocity";  
427 +      angularVelocity.dataType = "Vector3d";
428 +      angularVelocity.accumulator.reserve(nBins_);
429 +      for (int i = 0; i < nBins_; i++)
430 +        angularVelocity.accumulator.push_back( new VectorAccumulator() );
431 +      data_[ANGULARVELOCITY] = angularVelocity;
432 +      outputMap_["ANGULARVELOCITY"] = ANGULARVELOCITY;
433 +
434        OutputData density;
435        density.units =  "g cm^-3";
436        density.title =  "Density";
# Line 546 | Line 557 | namespace OpenMD {
557              slabWidth_ = hmat(2,2) / 10.0;
558          
559            if (hasSlabBCenter)
560 <            slabBCenter_ = rnemdParams->getSlabACenter();
560 >            slabBCenter_ = rnemdParams->getSlabBCenter();
561            else
562              slabBCenter_ = hmat(2,2) / 2.0;
563          
# Line 567 | Line 578 | namespace OpenMD {
578          }
579        }
580      }
581 +
582      // object evaluator:
583      evaluator_.loadScriptString(rnemdObjectSelection_);
584      seleMan_.setSelectionSet(evaluator_.evaluate());
573    
585      evaluatorA_.loadScriptString(selectionA_);
586      evaluatorB_.loadScriptString(selectionB_);
576    
587      seleManA_.setSelectionSet(evaluatorA_.evaluate());
588      seleManB_.setSelectionSet(evaluatorB_.evaluate());
579    
589      commonA_ = seleManA_ & seleMan_;
590 <    commonB_ = seleManB_ & seleMan_;    
590 >    commonB_ = seleManB_ & seleMan_;  
591    }
592    
593      
# Line 595 | Line 604 | namespace OpenMD {
604   #ifdef IS_MPI
605      }
606   #endif
607 +
608 +    // delete all of the objects we created:
609 +    delete areaAccumulator_;    
610 +    data_.clear();
611    }
612    
613    void RNEMD::doSwap(SelectionManager& smanA, SelectionManager& smanB) {
# Line 1138 | Line 1151 | namespace OpenMD {
1151            //if w is in the right range, so should be x, y, z.
1152            vector<StuntDouble*>::iterator sdi;
1153            Vector3d vel;
1154 <          for (sdi = coldBin.begin(); sdi != coldBin.end(); sdi++) {
1154 >          for (sdi = coldBin.begin(); sdi != coldBin.end(); ++sdi) {
1155              if (rnemdFluxType_ == rnemdFullKE) {
1156                vel = (*sdi)->getVel() * c;
1157                (*sdi)->setVel(vel);
# Line 1149 | Line 1162 | namespace OpenMD {
1162              }
1163            }
1164            w = sqrt(w);
1165 <          for (sdi = hotBin.begin(); sdi != hotBin.end(); sdi++) {
1165 >          for (sdi = hotBin.begin(); sdi != hotBin.end(); ++sdi) {
1166              if (rnemdFluxType_ == rnemdFullKE) {
1167                vel = (*sdi)->getVel();
1168                vel.x() *= x;
# Line 1268 | Line 1281 | namespace OpenMD {
1281        vector<RealType>::iterator ri;
1282        RealType r1, r2, alpha0;
1283        vector<pair<RealType,RealType> > rps;
1284 <      for (ri = realRoots.begin(); ri !=realRoots.end(); ri++) {
1284 >      for (ri = realRoots.begin(); ri !=realRoots.end(); ++ri) {
1285          r2 = *ri;
1286          //check if FindRealRoots() give the right answer
1287          if ( fabs(u0 + r2 * (u1 + r2 * (u2 + r2 * (u3 + r2 * u4)))) > 1e-6 ) {
# Line 1300 | Line 1313 | namespace OpenMD {
1313          RealType diff;
1314          pair<RealType,RealType> bestPair = make_pair(1.0, 1.0);
1315          vector<pair<RealType,RealType> >::iterator rpi;
1316 <        for (rpi = rps.begin(); rpi != rps.end(); rpi++) {
1316 >        for (rpi = rps.begin(); rpi != rps.end(); ++rpi) {
1317            r1 = (*rpi).first;
1318            r2 = (*rpi).second;
1319            switch(rnemdFluxType_) {
# Line 1367 | Line 1380 | namespace OpenMD {
1380          }
1381          vector<StuntDouble*>::iterator sdi;
1382          Vector3d vel;
1383 <        for (sdi = coldBin.begin(); sdi != coldBin.end(); sdi++) {
1383 >        for (sdi = coldBin.begin(); sdi != coldBin.end(); ++sdi) {
1384            vel = (*sdi)->getVel();
1385            vel.x() *= x;
1386            vel.y() *= y;
# Line 1378 | Line 1391 | namespace OpenMD {
1391          x = 1.0 + px * (1.0 - x);
1392          y = 1.0 + py * (1.0 - y);
1393          z = 1.0 + pz * (1.0 - z);
1394 <        for (sdi = hotBin.begin(); sdi != hotBin.end(); sdi++) {
1394 >        for (sdi = hotBin.begin(); sdi != hotBin.end(); ++sdi) {
1395            vel = (*sdi)->getVel();
1396            vel.x() *= x;
1397            vel.y() *= y;
# Line 1435 | Line 1448 | namespace OpenMD {
1448      RealType Mc = 0.0;
1449      Mat3x3d Ic(0.0);
1450      RealType Kc = 0.0;
1451 +
1452 +    // Constraints can be on only the linear or angular momentum, but
1453 +    // not both.  Usually, the user will specify which they want, but
1454 +    // in case they don't, the use of periodic boundaries should make
1455 +    // the choice for us.
1456 +    bool doLinearPart = false;
1457 +    bool doAngularPart = false;
1458 +
1459 +    switch (rnemdFluxType_) {
1460 +    case rnemdPx:
1461 +    case rnemdPy:
1462 +    case rnemdPz:
1463 +    case rnemdPvector:
1464 +    case rnemdKePx:
1465 +    case rnemdKePy:
1466 +    case rnemdKePvector:
1467 +      doLinearPart = true;
1468 +      break;
1469 +    case rnemdLx:
1470 +    case rnemdLy:
1471 +    case rnemdLz:
1472 +    case rnemdLvector:
1473 +    case rnemdKeLx:
1474 +    case rnemdKeLy:
1475 +    case rnemdKeLz:
1476 +    case rnemdKeLvector:
1477 +      doAngularPart = true;
1478 +      break;
1479 +    case rnemdKE:
1480 +    case rnemdRotKE:
1481 +    case rnemdFullKE:
1482 +    default:
1483 +      if (usePeriodicBoundaryConditions_)
1484 +        doLinearPart = true;
1485 +      else
1486 +        doAngularPart = true;
1487 +      break;
1488 +    }
1489      
1490      for (sd = smanA.beginSelected(selei); sd != NULL;
1491           sd = smanA.nextSelected(selei)) {
# Line 1543 | Line 1594 | namespace OpenMD {
1594                                MPI::REALTYPE, MPI::SUM);
1595   #endif
1596      
1597 +
1598 +    Vector3d ac, acrec, bc, bcrec;
1599 +    Vector3d ah, ahrec, bh, bhrec;
1600 +    RealType cNumerator, cDenominator;
1601 +    RealType hNumerator, hDenominator;
1602 +
1603 +
1604      bool successfulExchange = false;
1605      if ((Mh > 0.0) && (Mc > 0.0)) {//both slabs are not empty
1606        Vector3d vc = Pc / Mc;
1607 <      Vector3d ac = -momentumTarget_ / Mc + vc;
1608 <      Vector3d acrec = -momentumTarget_ / Mc;
1607 >      ac = -momentumTarget_ / Mc + vc;
1608 >      acrec = -momentumTarget_ / Mc;
1609        
1610        // We now need the inverse of the inertia tensor to calculate the
1611        // angular velocity of the cold slab;
1612        Mat3x3d Ici = Ic.inverse();
1613        Vector3d omegac = Ici * Lc;
1614 <      Vector3d bc  = -(Ici * angularMomentumTarget_) + omegac;
1615 <      Vector3d bcrec = bc - omegac;
1614 >      bc  = -(Ici * angularMomentumTarget_) + omegac;
1615 >      bcrec = bc - omegac;
1616        
1617 <      RealType cNumerator = Kc - kineticTarget_
1618 <        - 0.5 * Mc * ac.lengthSquare() - 0.5 * ( dot(bc, Ic * bc));
1617 >      cNumerator = Kc - kineticTarget_;
1618 >      if (doLinearPart)
1619 >        cNumerator -= 0.5 * Mc * ac.lengthSquare();
1620 >      
1621 >      if (doAngularPart)
1622 >        cNumerator -= 0.5 * ( dot(bc, Ic * bc));
1623 >
1624        if (cNumerator > 0.0) {
1625          
1626 <        RealType cDenominator = Kc - 0.5 * Mc * vc.lengthSquare()
1627 <          - 0.5*(dot(omegac, Ic * omegac));
1626 >        cDenominator = Kc;
1627 >
1628 >        if (doLinearPart)
1629 >          cDenominator -= 0.5 * Mc * vc.lengthSquare();
1630 >
1631 >        if (doAngularPart)
1632 >          cDenominator -= 0.5*(dot(omegac, Ic * omegac));
1633          
1634          if (cDenominator > 0.0) {
1635            RealType c = sqrt(cNumerator / cDenominator);
1636            if ((c > 0.9) && (c < 1.1)) {//restrict scaling coefficients
1637              
1638              Vector3d vh = Ph / Mh;
1639 <            Vector3d ah = momentumTarget_ / Mh + vh;
1640 <            Vector3d ahrec = momentumTarget_ / Mh;
1639 >            ah = momentumTarget_ / Mh + vh;
1640 >            ahrec = momentumTarget_ / Mh;
1641              
1642              // We now need the inverse of the inertia tensor to
1643              // calculate the angular velocity of the hot slab;
1644              Mat3x3d Ihi = Ih.inverse();
1645              Vector3d omegah = Ihi * Lh;
1646 <            Vector3d bh  = (Ihi * angularMomentumTarget_) + omegah;
1647 <            Vector3d bhrec = bh - omegah;
1646 >            bh  = (Ihi * angularMomentumTarget_) + omegah;
1647 >            bhrec = bh - omegah;
1648              
1649 <            RealType hNumerator = Kh + kineticTarget_
1650 <              - 0.5 * Mh * ah.lengthSquare() - 0.5 * ( dot(bh, Ih * bh));;
1649 >            hNumerator = Kh + kineticTarget_;
1650 >            if (doLinearPart)
1651 >              hNumerator -= 0.5 * Mh * ah.lengthSquare();
1652 >            
1653 >            if (doAngularPart)
1654 >              hNumerator -= 0.5 * ( dot(bh, Ih * bh));
1655 >              
1656              if (hNumerator > 0.0) {
1657                
1658 <              RealType hDenominator = Kh - 0.5 * Mh * vh.lengthSquare()
1659 <                - 0.5*(dot(omegah, Ih * omegah));
1658 >              hDenominator = Kh;
1659 >              if (doLinearPart)
1660 >                hDenominator -= 0.5 * Mh * vh.lengthSquare();
1661 >              if (doAngularPart)
1662 >                hDenominator -= 0.5*(dot(omegah, Ih * omegah));
1663                
1664                if (hDenominator > 0.0) {
1665                  RealType h = sqrt(hNumerator / hDenominator);
# Line 1593 | Line 1669 | namespace OpenMD {
1669                    Vector3d vel;
1670                    Vector3d rPos;
1671                    
1672 <                  for (sdi = coldBin.begin(); sdi != coldBin.end(); sdi++) {
1672 >                  for (sdi = coldBin.begin(); sdi != coldBin.end(); ++sdi) {
1673                      //vel = (*sdi)->getVel();
1674                      rPos = (*sdi)->getPos() - coordinateOrigin_;
1675 <                    vel = ((*sdi)->getVel() - vc - cross(omegac, rPos)) * c
1676 <                      + ac + cross(bc, rPos);
1675 >                    if (doLinearPart)
1676 >                      vel = ((*sdi)->getVel() - vc) * c + ac;
1677 >                    if (doAngularPart)
1678 >                      vel = ((*sdi)->getVel() - cross(omegac, rPos)) * c + cross(bc, rPos);
1679 >
1680                      (*sdi)->setVel(vel);
1681                      if (rnemdFluxType_ == rnemdFullKE) {
1682                        if ((*sdi)->isDirectional()) {
# Line 1606 | Line 1685 | namespace OpenMD {
1685                        }
1686                      }
1687                    }
1688 <                  for (sdi = hotBin.begin(); sdi != hotBin.end(); sdi++) {
1688 >                  for (sdi = hotBin.begin(); sdi != hotBin.end(); ++sdi) {
1689                      //vel = (*sdi)->getVel();
1690                      rPos = (*sdi)->getPos() - coordinateOrigin_;
1691 <                    vel = ((*sdi)->getVel() - vh - cross(omegah, rPos)) * h
1692 <                      + ah + cross(bh, rPos);                  
1691 >                    if (doLinearPart)
1692 >                      vel = ((*sdi)->getVel() - vh) * h + ah;    
1693 >                    if (doAngularPart)
1694 >                      vel = ((*sdi)->getVel() - cross(omegah, rPos)) * h + cross(bh, rPos);    
1695 >
1696                      (*sdi)->setVel(vel);
1697                      if (rnemdFluxType_ == rnemdFullKE) {
1698                        if ((*sdi)->isDirectional()) {
# Line 1653 | Line 1735 | namespace OpenMD {
1735        int isd;
1736        StuntDouble* sd;
1737        vector<StuntDouble*> aSites;
1656      ConvexHull* surfaceMeshA = new ConvexHull();
1738        seleManA_.setSelectionSet(evaluatorA_.evaluate());
1739        for (sd = seleManA_.beginSelected(isd); sd != NULL;
1740             sd = seleManA_.nextSelected(isd)) {
1741          aSites.push_back(sd);
1742        }
1743 +      ConvexHull* surfaceMeshA = new ConvexHull();
1744        surfaceMeshA->computeHull(aSites);
1745        areaA = surfaceMeshA->getArea();
1746 +      delete surfaceMeshA;
1747 +
1748      } else {
1749        if (usePeriodicBoundaryConditions_) {
1750          // in periodic boundaries, the surface area is twice the x-y
# Line 1674 | Line 1758 | namespace OpenMD {
1758        }
1759      }
1760  
1761 +
1762 +
1763      if (hasSelectionB_) {
1764        int isd;
1765        StuntDouble* sd;
1766        vector<StuntDouble*> bSites;
1681      ConvexHull* surfaceMeshB = new ConvexHull();
1767        seleManB_.setSelectionSet(evaluatorB_.evaluate());
1768        for (sd = seleManB_.beginSelected(isd); sd != NULL;
1769             sd = seleManB_.nextSelected(isd)) {
1770          bSites.push_back(sd);
1771        }
1772 +      ConvexHull* surfaceMeshB = new ConvexHull();    
1773        surfaceMeshB->computeHull(bSites);
1774        areaB = surfaceMeshB->getArea();
1775 +      delete surfaceMeshB;
1776 +
1777      } else {
1778        if (usePeriodicBoundaryConditions_) {
1779          // in periodic boundaries, the surface area is twice the x-y
# Line 1751 | Line 1839 | namespace OpenMD {
1839    void RNEMD::collectData() {
1840      if (!doRNEMD_) return;
1841      Snapshot* currentSnap_ = info_->getSnapshotManager()->getCurrentSnapshot();
1842 <
1842 >    
1843      // collectData can be called more frequently than the doRNEMD, so use the
1844      // computed area from the last exchange time:
1845 <
1846 <    areaAccumulator_->add(getDividingArea());
1845 >    RealType area = getDividingArea();
1846 >    areaAccumulator_->add(area);
1847      Mat3x3d hmat = currentSnap_->getHmat();
1848      seleMan_.setSelectionSet(evaluator_.evaluate());
1849  
# Line 1814 | Line 1902 | namespace OpenMD {
1902        Vector3d rPos = sd->getPos() - coordinateOrigin_;
1903        Vector3d aVel = cross(rPos, vel);
1904        
1905 <      if (binNo < nBins_)  {
1905 >      if (binNo >= 0 && binNo < nBins_)  {
1906          binCount[binNo]++;
1907          binMass[binNo] += mass;
1908          binPx[binNo] += mass*vel.x();
# Line 1890 | Line 1978 | namespace OpenMD {
1978        vel.x() = binPx[i] / binMass[i];
1979        vel.y() = binPy[i] / binMass[i];
1980        vel.z() = binPz[i] / binMass[i];
1981 <      aVel.x() = binOmegax[i];
1982 <      aVel.y() = binOmegay[i];
1983 <      aVel.z() = binOmegaz[i];
1981 >      aVel.x() = binOmegax[i] / binCount[i];
1982 >      aVel.y() = binOmegay[i] / binCount[i];
1983 >      aVel.z() = binOmegaz[i] / binCount[i];
1984  
1985        if (binCount[i] > 0) {
1986          // only add values if there are things to add
# Line 1914 | Line 2002 | namespace OpenMD {
2002              case VELOCITY:
2003                dynamic_cast<VectorAccumulator *>(data_[j].accumulator[i])->add(vel);
2004                break;
2005 <            case ANGULARVELOCITY:
2005 >            case ANGULARVELOCITY:  
2006                dynamic_cast<VectorAccumulator *>(data_[j].accumulator[i])->add(aVel);
2007                break;
2008              case DENSITY:
# Line 1925 | Line 2013 | namespace OpenMD {
2013          }
2014        }
2015      }
2016 +    hasData_ = true;
2017    }
2018  
2019    void RNEMD::getStarted() {
# Line 1957 | Line 2046 | namespace OpenMD {
2046    
2047    void RNEMD::writeOutputFile() {
2048      if (!doRNEMD_) return;
2049 +    if (!hasData_) return;
2050      
2051   #ifdef IS_MPI
2052      // If we're the root node, should we print out the results
# Line 1978 | Line 2068 | namespace OpenMD {
2068        RealType time = currentSnap_->getTime();
2069        RealType avgArea;
2070        areaAccumulator_->getAverage(avgArea);
1981      RealType Jz = kineticExchange_ / (time * avgArea)
1982        / PhysicalConstants::energyConvert;
1983      Vector3d JzP = momentumExchange_ / (time * avgArea);      
1984      Vector3d JzL = angularMomentumExchange_ / (time * avgArea);      
2071  
2072 +      RealType Jz(0.0);
2073 +      Vector3d JzP(V3Zero);
2074 +      Vector3d JzL(V3Zero);
2075 +      if (time >= info_->getSimParams()->getDt()) {
2076 +        Jz = kineticExchange_ / (time * avgArea)
2077 +          / PhysicalConstants::energyConvert;
2078 +        JzP = momentumExchange_ / (time * avgArea);
2079 +        JzL = angularMomentumExchange_ / (time * avgArea);
2080 +      }
2081 +
2082        rnemdFile_ << "#######################################################\n";
2083        rnemdFile_ << "# RNEMD {\n";
2084  
# Line 2069 | Line 2165 | namespace OpenMD {
2165            if (outputMask_[i]) {
2166              if (data_[i].dataType == "RealType")
2167                writeReal(i,j);
2168 <            else if (data_[i].dataType == "Vector3d")
2168 >            else if (data_[i].dataType == "Vector3d")
2169                writeVector(i,j);
2170              else {
2171                sprintf( painCave.errMsg,
# Line 2126 | Line 2222 | namespace OpenMD {
2222      RealType s;
2223      int count;
2224      
2225 <    count = dynamic_cast<Accumulator *>(data_[index].accumulator[bin])->count();
2225 >    count = data_[index].accumulator[bin]->count();
2226      if (count == 0) return;
2227      
2228      dynamic_cast<Accumulator *>(data_[index].accumulator[bin])->getAverage(s);
# Line 2135 | Line 2231 | namespace OpenMD {
2231        rnemdFile_ << "\t" << s;
2232      } else{
2233        sprintf( painCave.errMsg,
2234 <               "RNEMD detected a numerical error writing: %s for bin %d",
2234 >               "RNEMD detected a numerical error writing: %s for bin %u",
2235                 data_[index].title.c_str(), bin);
2236        painCave.isFatal = 1;
2237        simError();
# Line 2149 | Line 2245 | namespace OpenMD {
2245      Vector3d s;
2246      int count;
2247      
2248 <    count = dynamic_cast<Accumulator *>(data_[index].accumulator[bin])->count();
2248 >    count = data_[index].accumulator[bin]->count();
2249 >
2250      if (count == 0) return;
2251  
2252      dynamic_cast<VectorAccumulator*>(data_[index].accumulator[bin])->getAverage(s);
# Line 2157 | Line 2254 | namespace OpenMD {
2254          isinf(s[1]) || isnan(s[1]) ||
2255          isinf(s[2]) || isnan(s[2]) ) {      
2256        sprintf( painCave.errMsg,
2257 <               "RNEMD detected a numerical error writing: %s for bin %d",
2257 >               "RNEMD detected a numerical error writing: %s for bin %u",
2258                 data_[index].title.c_str(), bin);
2259        painCave.isFatal = 1;
2260        simError();
# Line 2173 | Line 2270 | namespace OpenMD {
2270      RealType s;
2271      int count;
2272      
2273 <    count = dynamic_cast<Accumulator *>(data_[index].accumulator[bin])->count();
2273 >    count = data_[index].accumulator[bin]->count();
2274      if (count == 0) return;
2275      
2276      dynamic_cast<Accumulator *>(data_[index].accumulator[bin])->getStdDev(s);
# Line 2182 | Line 2279 | namespace OpenMD {
2279        rnemdFile_ << "\t" << s;
2280      } else{
2281        sprintf( painCave.errMsg,
2282 <               "RNEMD detected a numerical error writing: %s std. dev. for bin %d",
2282 >               "RNEMD detected a numerical error writing: %s std. dev. for bin %u",
2283                 data_[index].title.c_str(), bin);
2284        painCave.isFatal = 1;
2285        simError();
# Line 2196 | Line 2293 | namespace OpenMD {
2293      Vector3d s;
2294      int count;
2295      
2296 <    count = dynamic_cast<Accumulator *>(data_[index].accumulator[bin])->count();
2296 >    count = data_[index].accumulator[bin]->count();
2297      if (count == 0) return;
2298  
2299      dynamic_cast<VectorAccumulator*>(data_[index].accumulator[bin])->getStdDev(s);
# Line 2204 | Line 2301 | namespace OpenMD {
2301          isinf(s[1]) || isnan(s[1]) ||
2302          isinf(s[2]) || isnan(s[2]) ) {      
2303        sprintf( painCave.errMsg,
2304 <               "RNEMD detected a numerical error writing: %s std. dev. for bin %d",
2304 >               "RNEMD detected a numerical error writing: %s std. dev. for bin %u",
2305                 data_[index].title.c_str(), bin);
2306        painCave.isFatal = 1;
2307        simError();

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines