| 1445 | 
  | 
    RealType Mc = 0.0; | 
| 1446 | 
  | 
    Mat3x3d Ic(0.0); | 
| 1447 | 
  | 
    RealType Kc = 0.0; | 
| 1448 | 
+ | 
 | 
| 1449 | 
+ | 
    // Constraints can be on only the linear or angular momentum, but | 
| 1450 | 
+ | 
    // not both.  Usually, the user will specify which they want, but | 
| 1451 | 
+ | 
    // in case they don't, the use of periodic boundaries should make | 
| 1452 | 
+ | 
    // the choice for us. | 
| 1453 | 
+ | 
    bool doLinearPart = false; | 
| 1454 | 
+ | 
    bool doAngularPart = false; | 
| 1455 | 
+ | 
 | 
| 1456 | 
+ | 
    switch (rnemdFluxType_) { | 
| 1457 | 
+ | 
    case rnemdPx: | 
| 1458 | 
+ | 
    case rnemdPy: | 
| 1459 | 
+ | 
    case rnemdPz: | 
| 1460 | 
+ | 
    case rnemdPvector: | 
| 1461 | 
+ | 
    case rnemdKePx: | 
| 1462 | 
+ | 
    case rnemdKePy: | 
| 1463 | 
+ | 
    case rnemdKePvector: | 
| 1464 | 
+ | 
      doLinearPart = true; | 
| 1465 | 
+ | 
      break; | 
| 1466 | 
+ | 
    case rnemdLx: | 
| 1467 | 
+ | 
    case rnemdLy: | 
| 1468 | 
+ | 
    case rnemdLz: | 
| 1469 | 
+ | 
    case rnemdLvector: | 
| 1470 | 
+ | 
    case rnemdKeLx: | 
| 1471 | 
+ | 
    case rnemdKeLy: | 
| 1472 | 
+ | 
    case rnemdKeLz: | 
| 1473 | 
+ | 
    case rnemdKeLvector: | 
| 1474 | 
+ | 
      doAngularPart = true; | 
| 1475 | 
+ | 
      break; | 
| 1476 | 
+ | 
    case rnemdKE: | 
| 1477 | 
+ | 
    case rnemdRotKE: | 
| 1478 | 
+ | 
    case rnemdFullKE: | 
| 1479 | 
+ | 
    default: | 
| 1480 | 
+ | 
      if (usePeriodicBoundaryConditions_)  | 
| 1481 | 
+ | 
        doLinearPart = true; | 
| 1482 | 
+ | 
      else | 
| 1483 | 
+ | 
        doAngularPart = true; | 
| 1484 | 
+ | 
      break; | 
| 1485 | 
+ | 
    } | 
| 1486 | 
  | 
     | 
| 1487 | 
  | 
    for (sd = smanA.beginSelected(selei); sd != NULL;  | 
| 1488 | 
  | 
         sd = smanA.nextSelected(selei)) { | 
| 1591 | 
  | 
                              MPI::REALTYPE, MPI::SUM); | 
| 1592 | 
  | 
#endif | 
| 1593 | 
  | 
     | 
| 1594 | 
+ | 
 | 
| 1595 | 
+ | 
    Vector3d ac, acrec, bc, bcrec; | 
| 1596 | 
+ | 
    Vector3d ah, ahrec, bh, bhrec; | 
| 1597 | 
+ | 
    RealType cNumerator, cDenominator; | 
| 1598 | 
+ | 
    RealType hNumerator, hDenominator; | 
| 1599 | 
+ | 
 | 
| 1600 | 
+ | 
 | 
| 1601 | 
  | 
    bool successfulExchange = false; | 
| 1602 | 
  | 
    if ((Mh > 0.0) && (Mc > 0.0)) {//both slabs are not empty | 
| 1603 | 
  | 
      Vector3d vc = Pc / Mc; | 
| 1604 | 
< | 
      Vector3d ac = -momentumTarget_ / Mc + vc; | 
| 1605 | 
< | 
      Vector3d acrec = -momentumTarget_ / Mc; | 
| 1604 | 
> | 
      ac = -momentumTarget_ / Mc + vc; | 
| 1605 | 
> | 
      acrec = -momentumTarget_ / Mc; | 
| 1606 | 
  | 
       | 
| 1607 | 
  | 
      // We now need the inverse of the inertia tensor to calculate the  | 
| 1608 | 
  | 
      // angular velocity of the cold slab; | 
| 1609 | 
  | 
      Mat3x3d Ici = Ic.inverse(); | 
| 1610 | 
  | 
      Vector3d omegac = Ici * Lc; | 
| 1611 | 
< | 
      Vector3d bc  = -(Ici * angularMomentumTarget_) + omegac; | 
| 1612 | 
< | 
      Vector3d bcrec = bc - omegac; | 
| 1611 | 
> | 
      bc  = -(Ici * angularMomentumTarget_) + omegac; | 
| 1612 | 
> | 
      bcrec = bc - omegac; | 
| 1613 | 
  | 
       | 
| 1614 | 
< | 
      RealType cNumerator = Kc - kineticTarget_  | 
| 1615 | 
< | 
        - 0.5 * Mc * ac.lengthSquare() - 0.5 * ( dot(bc, Ic * bc)); | 
| 1614 | 
> | 
      cNumerator = Kc - kineticTarget_; | 
| 1615 | 
> | 
      if (doLinearPart)  | 
| 1616 | 
> | 
        cNumerator -= 0.5 * Mc * ac.lengthSquare(); | 
| 1617 | 
> | 
       | 
| 1618 | 
> | 
      if (doAngularPart) | 
| 1619 | 
> | 
        cNumerator -= 0.5 * ( dot(bc, Ic * bc)); | 
| 1620 | 
> | 
 | 
| 1621 | 
  | 
      if (cNumerator > 0.0) { | 
| 1622 | 
  | 
         | 
| 1623 | 
< | 
        RealType cDenominator = Kc - 0.5 * Mc * vc.lengthSquare()  | 
| 1624 | 
< | 
          - 0.5*(dot(omegac, Ic * omegac)); | 
| 1623 | 
> | 
        cDenominator = Kc; | 
| 1624 | 
> | 
 | 
| 1625 | 
> | 
        if (doLinearPart) | 
| 1626 | 
> | 
          cDenominator -= 0.5 * Mc * vc.lengthSquare(); | 
| 1627 | 
> | 
 | 
| 1628 | 
> | 
        if (doAngularPart) | 
| 1629 | 
> | 
          cDenominator -= 0.5*(dot(omegac, Ic * omegac)); | 
| 1630 | 
  | 
         | 
| 1631 | 
  | 
        if (cDenominator > 0.0) { | 
| 1632 | 
  | 
          RealType c = sqrt(cNumerator / cDenominator); | 
| 1633 | 
  | 
          if ((c > 0.9) && (c < 1.1)) {//restrict scaling coefficients | 
| 1634 | 
  | 
             | 
| 1635 | 
  | 
            Vector3d vh = Ph / Mh; | 
| 1636 | 
< | 
            Vector3d ah = momentumTarget_ / Mh + vh; | 
| 1637 | 
< | 
            Vector3d ahrec = momentumTarget_ / Mh; | 
| 1636 | 
> | 
            ah = momentumTarget_ / Mh + vh; | 
| 1637 | 
> | 
            ahrec = momentumTarget_ / Mh; | 
| 1638 | 
  | 
             | 
| 1639 | 
  | 
            // We now need the inverse of the inertia tensor to | 
| 1640 | 
  | 
            // calculate the angular velocity of the hot slab; | 
| 1641 | 
  | 
            Mat3x3d Ihi = Ih.inverse(); | 
| 1642 | 
  | 
            Vector3d omegah = Ihi * Lh; | 
| 1643 | 
< | 
            Vector3d bh  = (Ihi * angularMomentumTarget_) + omegah; | 
| 1644 | 
< | 
            Vector3d bhrec = bh - omegah; | 
| 1643 | 
> | 
            bh  = (Ihi * angularMomentumTarget_) + omegah; | 
| 1644 | 
> | 
            bhrec = bh - omegah; | 
| 1645 | 
  | 
             | 
| 1646 | 
< | 
            RealType hNumerator = Kh + kineticTarget_ | 
| 1647 | 
< | 
              - 0.5 * Mh * ah.lengthSquare() - 0.5 * ( dot(bh, Ih * bh));; | 
| 1646 | 
> | 
            hNumerator = Kh + kineticTarget_; | 
| 1647 | 
> | 
            if (doLinearPart)  | 
| 1648 | 
> | 
              hNumerator -= 0.5 * Mh * ah.lengthSquare(); | 
| 1649 | 
> | 
             | 
| 1650 | 
> | 
            if (doAngularPart) | 
| 1651 | 
> | 
              hNumerator -= 0.5 * ( dot(bh, Ih * bh)); | 
| 1652 | 
> | 
               | 
| 1653 | 
  | 
            if (hNumerator > 0.0) { | 
| 1654 | 
  | 
               | 
| 1655 | 
< | 
              RealType hDenominator = Kh - 0.5 * Mh * vh.lengthSquare()  | 
| 1656 | 
< | 
                - 0.5*(dot(omegah, Ih * omegah)); | 
| 1655 | 
> | 
              hDenominator = Kh; | 
| 1656 | 
> | 
              if (doLinearPart)  | 
| 1657 | 
> | 
                hDenominator -= 0.5 * Mh * vh.lengthSquare(); | 
| 1658 | 
> | 
              if (doAngularPart) | 
| 1659 | 
> | 
                hDenominator -= 0.5*(dot(omegah, Ih * omegah)); | 
| 1660 | 
  | 
               | 
| 1661 | 
  | 
              if (hDenominator > 0.0) { | 
| 1662 | 
  | 
                RealType h = sqrt(hNumerator / hDenominator); | 
| 1669 | 
  | 
                  for (sdi = coldBin.begin(); sdi != coldBin.end(); sdi++) { | 
| 1670 | 
  | 
                    //vel = (*sdi)->getVel(); | 
| 1671 | 
  | 
                    rPos = (*sdi)->getPos() - coordinateOrigin_; | 
| 1672 | 
< | 
                    vel = ((*sdi)->getVel() - vc - cross(omegac, rPos)) * c  | 
| 1673 | 
< | 
                      + ac + cross(bc, rPos); | 
| 1672 | 
> | 
                    if (doLinearPart) | 
| 1673 | 
> | 
                      vel = ((*sdi)->getVel() - vc) * c + ac; | 
| 1674 | 
> | 
                    if (doAngularPart) | 
| 1675 | 
> | 
                      vel = ((*sdi)->getVel() - cross(omegac, rPos)) * c + cross(bc, rPos); | 
| 1676 | 
> | 
 | 
| 1677 | 
  | 
                    (*sdi)->setVel(vel); | 
| 1678 | 
  | 
                    if (rnemdFluxType_ == rnemdFullKE) { | 
| 1679 | 
  | 
                      if ((*sdi)->isDirectional()) { | 
| 1685 | 
  | 
                  for (sdi = hotBin.begin(); sdi != hotBin.end(); sdi++) { | 
| 1686 | 
  | 
                    //vel = (*sdi)->getVel(); | 
| 1687 | 
  | 
                    rPos = (*sdi)->getPos() - coordinateOrigin_; | 
| 1688 | 
< | 
                    vel = ((*sdi)->getVel() - vh - cross(omegah, rPos)) * h  | 
| 1689 | 
< | 
                      + ah + cross(bh, rPos);      | 
| 1688 | 
> | 
                    if (doLinearPart) | 
| 1689 | 
> | 
                      vel = ((*sdi)->getVel() - vh) * h + ah;      | 
| 1690 | 
> | 
                    if (doAngularPart) | 
| 1691 | 
> | 
                      vel = ((*sdi)->getVel() - cross(omegah, rPos)) * h + cross(bh, rPos);      | 
| 1692 | 
> | 
 | 
| 1693 | 
  | 
                    (*sdi)->setVel(vel); | 
| 1694 | 
  | 
                    if (rnemdFluxType_ == rnemdFullKE) { | 
| 1695 | 
  | 
                      if ((*sdi)->isDirectional()) { | 
| 1969 | 
  | 
      vel.x() = binPx[i] / binMass[i]; | 
| 1970 | 
  | 
      vel.y() = binPy[i] / binMass[i]; | 
| 1971 | 
  | 
      vel.z() = binPz[i] / binMass[i]; | 
| 1972 | 
< | 
      aVel.x() = binOmegax[i]; | 
| 1973 | 
< | 
      aVel.y() = binOmegay[i]; | 
| 1974 | 
< | 
      aVel.z() = binOmegaz[i]; | 
| 1972 | 
> | 
      aVel.x() = binOmegax[i] / binCount[i]; | 
| 1973 | 
> | 
      aVel.y() = binOmegay[i] / binCount[i]; | 
| 1974 | 
> | 
      aVel.z() = binOmegaz[i] / binCount[i]; | 
| 1975 | 
  | 
 | 
| 1976 | 
  | 
      if (binCount[i] > 0) { | 
| 1977 | 
  | 
        // only add values if there are things to add |