38 |
|
* [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008). |
39 |
|
* [4] Vardeman & Gezelter, in progress (2009). |
40 |
|
*/ |
41 |
+ |
#ifdef IS_MPI |
42 |
+ |
#include <mpi.h> |
43 |
+ |
#endif |
44 |
|
|
45 |
|
#include <cmath> |
46 |
|
#include <sstream> |
57 |
|
#include "utils/Tuple.hpp" |
58 |
|
#include "brains/Thermo.hpp" |
59 |
|
#include "math/ConvexHull.hpp" |
57 |
– |
#ifdef IS_MPI |
58 |
– |
#include <mpi.h> |
59 |
– |
#endif |
60 |
|
|
61 |
|
#ifdef _MSC_VER |
62 |
|
#define isnan(x) _isnan((x)) |
424 |
|
OutputData angularVelocity; |
425 |
|
angularVelocity.units = "angstroms^2/fs"; |
426 |
|
angularVelocity.title = "AngularVelocity"; |
427 |
< |
angularVelocity.dataType = "Vector3d"; |
427 |
> |
angularVelocity.dataType = "RealType"; |
428 |
|
angularVelocity.accumulator.reserve(nBins_); |
429 |
|
for (int i = 0; i < nBins_; i++) |
430 |
< |
angularVelocity.accumulator.push_back( new VectorAccumulator() ); |
430 |
> |
angularVelocity.accumulator.push_back( new Accumulator() ); |
431 |
|
data_[ANGULARVELOCITY] = angularVelocity; |
432 |
|
outputMap_["ANGULARVELOCITY"] = ANGULARVELOCITY; |
433 |
|
|
547 |
|
|
548 |
|
if (hasSelectionB_) { |
549 |
|
selectionB_ = rnemdParams->getSelectionB(); |
550 |
+ |
|
551 |
|
} else { |
552 |
|
if (usePeriodicBoundaryConditions_) { |
553 |
|
Mat3x3d hmat = currentSnap_->getHmat(); |
574 |
|
selectionB_ = selectionBstream.str(); |
575 |
|
} else { |
576 |
|
selectionB_ = "select hull"; |
577 |
+ |
BisHull_ = true; |
578 |
|
hasSelectionB_ = true; |
579 |
|
} |
580 |
|
} |
1731 |
|
Snapshot* snap = info_->getSnapshotManager()->getCurrentSnapshot(); |
1732 |
|
|
1733 |
|
if (hasSelectionA_) { |
1734 |
< |
int isd; |
1735 |
< |
StuntDouble* sd; |
1736 |
< |
vector<StuntDouble*> aSites; |
1737 |
< |
seleManA_.setSelectionSet(evaluatorA_.evaluate()); |
1738 |
< |
for (sd = seleManA_.beginSelected(isd); sd != NULL; |
1739 |
< |
sd = seleManA_.nextSelected(isd)) { |
1740 |
< |
aSites.push_back(sd); |
1741 |
< |
} |
1742 |
< |
#if defined(HAVE_QHULL) |
1743 |
< |
ConvexHull* surfaceMeshA = new ConvexHull(); |
1744 |
< |
surfaceMeshA->computeHull(aSites); |
1745 |
< |
areaA = surfaceMeshA->getArea(); |
1746 |
< |
delete surfaceMeshA; |
1747 |
< |
#else |
1748 |
< |
sprintf( painCave.errMsg, |
1749 |
< |
"RNEMD::getDividingArea : Hull calculation is not possible\n" |
1750 |
< |
"\twithout libqhull. Please rebuild OpenMD with qhull enabled."); |
1751 |
< |
painCave.severity = OPENMD_ERROR; |
1752 |
< |
painCave.isFatal = 1; |
1753 |
< |
simError(); |
1734 |
> |
|
1735 |
> |
if (evaluatorA_.hasSurfaceArea()) |
1736 |
> |
areaA = evaluatorA_.getSurfaceArea(); |
1737 |
> |
else { |
1738 |
> |
|
1739 |
> |
cerr << "selection A did not have surface area, recomputing\n"; |
1740 |
> |
int isd; |
1741 |
> |
StuntDouble* sd; |
1742 |
> |
vector<StuntDouble*> aSites; |
1743 |
> |
seleManA_.setSelectionSet(evaluatorA_.evaluate()); |
1744 |
> |
for (sd = seleManA_.beginSelected(isd); sd != NULL; |
1745 |
> |
sd = seleManA_.nextSelected(isd)) { |
1746 |
> |
aSites.push_back(sd); |
1747 |
> |
} |
1748 |
> |
#if defined(HAVE_QHULL) |
1749 |
> |
ConvexHull* surfaceMeshA = new ConvexHull(); |
1750 |
> |
surfaceMeshA->computeHull(aSites); |
1751 |
> |
areaA = surfaceMeshA->getArea(); |
1752 |
> |
delete surfaceMeshA; |
1753 |
> |
#else |
1754 |
> |
sprintf( painCave.errMsg, |
1755 |
> |
"RNEMD::getDividingArea : Hull calculation is not possible\n" |
1756 |
> |
"\twithout libqhull. Please rebuild OpenMD with qhull enabled."); |
1757 |
> |
painCave.severity = OPENMD_ERROR; |
1758 |
> |
painCave.isFatal = 1; |
1759 |
> |
simError(); |
1760 |
|
#endif |
1761 |
+ |
} |
1762 |
|
|
1763 |
|
} else { |
1764 |
|
if (usePeriodicBoundaryConditions_) { |
1774 |
|
} |
1775 |
|
|
1776 |
|
if (hasSelectionB_) { |
1777 |
< |
int isd; |
1778 |
< |
StuntDouble* sd; |
1779 |
< |
vector<StuntDouble*> bSites; |
1780 |
< |
seleManB_.setSelectionSet(evaluatorB_.evaluate()); |
1772 |
< |
for (sd = seleManB_.beginSelected(isd); sd != NULL; |
1773 |
< |
sd = seleManB_.nextSelected(isd)) { |
1774 |
< |
bSites.push_back(sd); |
1775 |
< |
} |
1777 |
> |
if (evaluatorB_.hasSurfaceArea()) |
1778 |
> |
areaB = evaluatorB_.getSurfaceArea(); |
1779 |
> |
else { |
1780 |
> |
cerr << "selection B did not have surface area, recomputing\n"; |
1781 |
|
|
1782 |
< |
#if defined(HAVE_QHULL) |
1783 |
< |
ConvexHull* surfaceMeshB = new ConvexHull(); |
1784 |
< |
surfaceMeshB->computeHull(bSites); |
1785 |
< |
areaB = surfaceMeshB->getArea(); |
1786 |
< |
delete surfaceMeshB; |
1782 |
> |
int isd; |
1783 |
> |
StuntDouble* sd; |
1784 |
> |
vector<StuntDouble*> bSites; |
1785 |
> |
seleManB_.setSelectionSet(evaluatorB_.evaluate()); |
1786 |
> |
for (sd = seleManB_.beginSelected(isd); sd != NULL; |
1787 |
> |
sd = seleManB_.nextSelected(isd)) { |
1788 |
> |
bSites.push_back(sd); |
1789 |
> |
} |
1790 |
> |
|
1791 |
> |
#if defined(HAVE_QHULL) |
1792 |
> |
ConvexHull* surfaceMeshB = new ConvexHull(); |
1793 |
> |
surfaceMeshB->computeHull(bSites); |
1794 |
> |
areaB = surfaceMeshB->getArea(); |
1795 |
> |
delete surfaceMeshB; |
1796 |
|
#else |
1797 |
< |
sprintf( painCave.errMsg, |
1798 |
< |
"RNEMD::getDividingArea : Hull calculation is not possible\n" |
1799 |
< |
"\twithout libqhull. Please rebuild OpenMD with qhull enabled."); |
1800 |
< |
painCave.severity = OPENMD_ERROR; |
1801 |
< |
painCave.isFatal = 1; |
1802 |
< |
simError(); |
1797 |
> |
sprintf( painCave.errMsg, |
1798 |
> |
"RNEMD::getDividingArea : Hull calculation is not possible\n" |
1799 |
> |
"\twithout libqhull. Please rebuild OpenMD with qhull enabled."); |
1800 |
> |
painCave.severity = OPENMD_ERROR; |
1801 |
> |
painCave.isFatal = 1; |
1802 |
> |
simError(); |
1803 |
|
#endif |
1804 |
< |
|
1805 |
< |
|
1804 |
> |
} |
1805 |
> |
|
1806 |
|
} else { |
1807 |
|
if (usePeriodicBoundaryConditions_) { |
1808 |
|
// in periodic boundaries, the surface area is twice the x-y |
1814 |
|
areaB = 4.0 * M_PI * pow(sphereBRadius_, 2); |
1815 |
|
} |
1816 |
|
} |
1817 |
< |
|
1817 |
> |
|
1818 |
|
dividingArea_ = min(areaA, areaB); |
1819 |
|
hasDividingArea_ = true; |
1820 |
|
return dividingArea_; |
1874 |
|
RealType area = getDividingArea(); |
1875 |
|
areaAccumulator_->add(area); |
1876 |
|
Mat3x3d hmat = currentSnap_->getHmat(); |
1877 |
+ |
Vector3d u = angularMomentumFluxVector_; |
1878 |
+ |
u.normalize(); |
1879 |
+ |
|
1880 |
|
seleMan_.setSelectionSet(evaluator_.evaluate()); |
1881 |
|
|
1882 |
|
int selei(0); |
1887 |
|
vector<RealType> binPx(nBins_, 0.0); |
1888 |
|
vector<RealType> binPy(nBins_, 0.0); |
1889 |
|
vector<RealType> binPz(nBins_, 0.0); |
1890 |
< |
vector<RealType> binOmegax(nBins_, 0.0); |
1874 |
< |
vector<RealType> binOmegay(nBins_, 0.0); |
1875 |
< |
vector<RealType> binOmegaz(nBins_, 0.0); |
1890 |
> |
vector<RealType> binOmega(nBins_, 0.0); |
1891 |
|
vector<RealType> binKE(nBins_, 0.0); |
1892 |
|
vector<int> binDOF(nBins_, 0); |
1893 |
|
vector<int> binCount(nBins_, 0); |
1927 |
|
binNo = int(rPos.length() / binWidth_); |
1928 |
|
} |
1929 |
|
|
1930 |
+ |
|
1931 |
|
RealType mass = sd->getMass(); |
1932 |
|
Vector3d vel = sd->getVel(); |
1933 |
|
Vector3d rPos = sd->getPos() - coordinateOrigin_; |
1934 |
< |
Vector3d aVel = cross(rPos, vel); |
1934 |
> |
// Project the relative position onto a plane perpendicular to |
1935 |
> |
// the angularMomentumFluxVector: |
1936 |
> |
Vector3d rProj = rPos - dot(rPos, u) * u; |
1937 |
> |
// Project the velocity onto a plane perpendicular to the |
1938 |
> |
// angularMomentumFluxVector: |
1939 |
> |
Vector3d vProj = vel - dot(vel, u) * u; |
1940 |
> |
// Compute angular velocity vector (should be nearly parallel to |
1941 |
> |
// angularMomentumFluxVector |
1942 |
> |
Vector3d aVel = cross(rProj, vProj); |
1943 |
|
|
1944 |
|
if (binNo >= 0 && binNo < nBins_) { |
1945 |
|
binCount[binNo]++; |
1947 |
|
binPx[binNo] += mass*vel.x(); |
1948 |
|
binPy[binNo] += mass*vel.y(); |
1949 |
|
binPz[binNo] += mass*vel.z(); |
1950 |
< |
binOmegax[binNo] += aVel.x(); |
1927 |
< |
binOmegay[binNo] += aVel.y(); |
1928 |
< |
binOmegaz[binNo] += aVel.z(); |
1950 |
> |
binOmega[binNo] += dot(aVel, u); |
1951 |
|
binKE[binNo] += 0.5 * (mass * vel.lengthSquare()); |
1952 |
|
binDOF[binNo] += 3; |
1953 |
|
|
1982 |
|
nBins_, MPI::REALTYPE, MPI::SUM); |
1983 |
|
MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &binPz[0], |
1984 |
|
nBins_, MPI::REALTYPE, MPI::SUM); |
1985 |
< |
MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &binOmegax[0], |
1964 |
< |
nBins_, MPI::REALTYPE, MPI::SUM); |
1965 |
< |
MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &binOmegay[0], |
1966 |
< |
nBins_, MPI::REALTYPE, MPI::SUM); |
1967 |
< |
MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &binOmegaz[0], |
1985 |
> |
MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &binOmega[0], |
1986 |
|
nBins_, MPI::REALTYPE, MPI::SUM); |
1987 |
|
MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &binKE[0], |
1988 |
|
nBins_, MPI::REALTYPE, MPI::SUM); |
1991 |
|
#endif |
1992 |
|
|
1993 |
|
Vector3d vel; |
1994 |
< |
Vector3d aVel; |
1994 |
> |
RealType omega; |
1995 |
|
RealType den; |
1996 |
|
RealType temp; |
1997 |
|
RealType z; |
2011 |
|
vel.x() = binPx[i] / binMass[i]; |
2012 |
|
vel.y() = binPy[i] / binMass[i]; |
2013 |
|
vel.z() = binPz[i] / binMass[i]; |
2014 |
< |
aVel.x() = binOmegax[i] / binCount[i]; |
1997 |
< |
aVel.y() = binOmegay[i] / binCount[i]; |
1998 |
< |
aVel.z() = binOmegaz[i] / binCount[i]; |
2014 |
> |
omega = binOmega[i] / binCount[i]; |
2015 |
|
|
2016 |
|
if (binCount[i] > 0) { |
2017 |
|
// only add values if there are things to add |
2034 |
|
dynamic_cast<VectorAccumulator *>(data_[j].accumulator[i])->add(vel); |
2035 |
|
break; |
2036 |
|
case ANGULARVELOCITY: |
2037 |
< |
dynamic_cast<VectorAccumulator *>(data_[j].accumulator[i])->add(aVel); |
2037 |
> |
dynamic_cast<Accumulator *>(data_[j].accumulator[i])->add(omega); |
2038 |
|
break; |
2039 |
|
case DENSITY: |
2040 |
|
dynamic_cast<Accumulator *>(data_[j].accumulator[i])->add(den); |