48#include "applications/staticProps/GofRAngle2.hpp"
55#include "types/MultipoleAdapter.hpp"
56#include "utils/Revision.hpp"
57#include "utils/simError.h"
61 GofRAngle2::GofRAngle2(
SimInfo* info,
const std::string& filename,
62 const std::string& sele1,
const std::string& sele2,
63 RealType len,
int nrbins,
int nangleBins) :
65 nAngleBins_(nangleBins), len_(len), doSele3_(false), seleMan3_(info),
67 setAnalysisType(
"Radial Distribution Function");
68 setOutputName(
getPrefix(filename) +
".grto");
70 deltaR_ = len_ / (double)nBins_;
71 deltaCosAngle_ = 2.0 / nAngleBins_;
73 std::stringstream params;
74 params <<
" nBins = " << nBins_ <<
", maxLen = " << len_
75 <<
", deltaR = " << deltaR_ <<
", nAngleBins = " << nAngleBins_
76 <<
", deltaCosAngle = " << deltaCosAngle_;
77 const std::string paramString = params.str();
78 setParameterString(paramString);
80 histogram_.resize(nBins_);
81 avgGofr_.resize(nBins_);
82 for (
unsigned int i = 0; i < nBins_; ++i) {
83 histogram_[i].resize(nAngleBins_);
84 avgGofr_[i].resize(nAngleBins_);
85 for (
unsigned int j = 0; j < nAngleBins_; ++j) {
86 histogram_[i][j].resize(nAngleBins_);
87 avgGofr_[i][j].resize(nAngleBins_);
92 GofRAngle2::GofRAngle2(SimInfo* info,
const std::string& filename,
93 const std::string& sele1,
const std::string& sele2,
94 const std::string& sele3, RealType len,
int nrbins,
96 RadialDistrFunc(info, filename, sele1, sele2, nrbins),
97 nAngleBins_(nangleBins), len_(len), doSele3_(true), seleMan3_(info),
98 evaluator3_(info), selectionScript3_(sele3) {
99 setOutputName(
getPrefix(filename) +
".grto");
101 deltaR_ = len_ / (double)nBins_;
102 deltaCosAngle_ = 2.0 / nAngleBins_;
104 std::stringstream params;
105 params <<
" nBins = " << nBins_ <<
", maxLen = " << len_
106 <<
", deltaR = " << deltaR_ <<
", nAngleBins = " << nAngleBins_
107 <<
", deltaCosAngle = " << deltaCosAngle_;
108 const std::string paramString = params.str();
109 setParameterString(paramString);
111 histogram_.resize(nBins_);
112 avgGofr_.resize(nBins_);
113 for (
unsigned int i = 0; i < nBins_; ++i) {
114 histogram_[i].resize(nAngleBins_);
115 avgGofr_[i].resize(nAngleBins_);
116 for (
unsigned int j = 0; j < nAngleBins_; ++j) {
117 histogram_[i][j].resize(nAngleBins_);
118 avgGofr_[i][j].resize(nAngleBins_);
122 evaluator3_.loadScriptString(sele3);
123 if (!evaluator3_.isDynamic()) {
124 seleMan3_.setSelectionSet(evaluator3_.evaluate());
128 void GofRAngle2::processNonOverlapping(SelectionManager& sman1,
129 SelectionManager& sman2) {
143 if (evaluator3_.isDynamic()) {
144 seleMan3_.setSelectionSet(evaluator3_.evaluate());
146 if (sman1.getSelectionCount() != seleMan3_.getSelectionCount()) {
147 RadialDistrFunc::processNonOverlapping(sman1, sman2);
150 for (sd1 = sman1.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
151 sd1 != NULL && sd3 != NULL;
152 sd1 = sman1.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
153 for (sd2 = sman2.beginSelected(j); sd2 != NULL;
154 sd2 = sman2.nextSelected(j)) {
155 collectHistogram(sd1, sd2, sd3);
159 RadialDistrFunc::processNonOverlapping(sman1, sman2);
163 void GofRAngle2::processOverlapping(SelectionManager& sman) {
177 if (evaluator3_.isDynamic()) {
178 seleMan3_.setSelectionSet(evaluator3_.evaluate());
180 if (sman.getSelectionCount() != seleMan3_.getSelectionCount()) {
181 RadialDistrFunc::processOverlapping(sman);
183 for (sd1 = sman.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
184 sd1 != NULL && sd3 != NULL;
185 sd1 = sman.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
186 for (j = i, sd2 = sman.nextSelected(j); sd2 != NULL;
187 sd2 = sman.nextSelected(j)) {
188 collectHistogram(sd1, sd2, sd3);
192 RadialDistrFunc::processOverlapping(sman);
196 void GofRAngle2::preProcess() {
197 for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
198 for (
unsigned int j = 0; j < avgGofr_[i].size(); ++j) {
199 std::fill(avgGofr_[i][j].begin(), avgGofr_[i][j].end(), 0.0);
204 void GofRAngle2::initializeHistogram() {
205 for (
unsigned int i = 0; i < histogram_.size(); ++i) {
206 for (
unsigned int j = 0; j < histogram_.size(); ++j) {
207 std::fill(histogram_[i][j].begin(), histogram_[i][j].end(), 0);
212 void GofRAngle2::processHistogram() {
213 int nPairs = getNPairs();
215 info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
216 RealType pairDensity = nPairs / volume;
217 RealType pairConstant = (4.0 * Constants::PI * pairDensity) /
218 (3.0 * (
double)nAngleBins_ * (
double)nAngleBins_);
220 for (
unsigned int i = 0; i < histogram_.size(); ++i) {
221 RealType rLower = i * deltaR_;
222 RealType rUpper = rLower + deltaR_;
224 (rUpper * rUpper * rUpper) - (rLower * rLower * rLower);
225 RealType nIdeal = volSlice * pairConstant;
227 for (
unsigned int j = 0; j < histogram_[i].size(); ++j) {
228 for (
unsigned int k = 0; k < histogram_[i][j].size(); ++k) {
229 avgGofr_[i][j][k] += RealType(histogram_[i][j][k]) / nIdeal;
235 void GofRAngle2::collectHistogram(StuntDouble* sd1, StuntDouble* sd2) {
236 bool usePeriodicBoundaryConditions_ =
237 info_->getSimParams()->getUsePeriodicBoundaryConditions();
239 if (sd1 == sd2) {
return; }
241 Vector3d pos1 = sd1->getPos();
242 Vector3d pos2 = sd2->getPos();
243 Vector3d r12 = pos1 - pos2;
244 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
247 int whichRBin = int(distance / deltaR_);
249 if (distance <= len_) {
250 if (!sd1->isDirectional()) {
251 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
252 "GofAngle2: attempted to use a non-directional object: %s\n",
253 sd1->getType().c_str());
254 painCave.isFatal = 1;
258 if (!sd2->isDirectional()) {
259 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
260 "GofAngle2: attempted to use a non-directional object: %s\n",
261 sd2->getType().c_str());
262 painCave.isFatal = 1;
266 Vector3d dipole1, dipole2;
269 AtomType* atype1 =
static_cast<Atom*
>(sd1)->getAtomType();
270 MultipoleAdapter ma1 = MultipoleAdapter(atype1);
272 dipole1 = sd1->getDipole();
274 dipole1 = sd1->getA().transpose() * V3Z;
277 dipole1 = sd1->getA().transpose() * V3Z;
281 AtomType* atype2 =
static_cast<Atom*
>(sd2)->getAtomType();
282 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
284 dipole2 = sd2->getDipole();
286 dipole2 = sd2->getA().transpose() * V3Z;
288 dipole2 = sd2->getA().transpose() * V3Z;
295 RealType cosAngle1 =
dot(r12, dipole1);
296 RealType cosAngle2 =
dot(dipole1, dipole2);
298 RealType halfBin = (nAngleBins_ - 1) * 0.5;
299 int angleBin1 = int(halfBin * (cosAngle1 + 1.0));
300 int angleBin2 = int(halfBin * (cosAngle2 + 1.0));
302 ++histogram_[whichRBin][angleBin1][angleBin2];
306 void GofRAngle2::collectHistogram(StuntDouble* sd1, StuntDouble* sd2,
308 bool usePeriodicBoundaryConditions_ =
309 info_->getSimParams()->getUsePeriodicBoundaryConditions();
311 if (sd1 == sd2) {
return; }
313 Vector3d p1 = sd1->getPos();
314 Vector3d p3 = sd3->getPos();
316 Vector3d c = 0.5 * (p1 + p3);
317 Vector3d r13 = p3 - p1;
319 Vector3d r12 = sd2->getPos() - c;
321 if (usePeriodicBoundaryConditions_) {
322 currentSnapshot_->wrapVector(r12);
323 currentSnapshot_->wrapVector(r13);
327 int whichRBin = int(distance / deltaR_);
329 if (distance <= len_) {
333 if (!sd2->isDirectional()) {
334 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
335 "GofAngle2: attempted to use a non-directional object: %s\n",
336 sd2->getType().c_str());
337 painCave.isFatal = 1;
344 AtomType* atype2 =
static_cast<Atom*
>(sd2)->getAtomType();
345 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
348 dipole2 = sd2->getDipole();
350 dipole2 = sd2->getA().transpose() * V3Z;
354 dipole2 = sd2->getA().transpose() * V3Z;
359 RealType cosAngle1 =
dot(r12, r13);
360 RealType cosAngle2 =
dot(r13, dipole2);
362 RealType halfBin = (nAngleBins_ - 1) * 0.5;
363 int angleBin1 = int(halfBin * (cosAngle1 + 1.0));
364 int angleBin2 = int(halfBin * (cosAngle2 + 1.0));
366 ++histogram_[whichRBin][angleBin1][angleBin2];
370 void GofRAngle2::writeRdf() {
371 std::ofstream ofs(outputFilename_.c_str());
374 ofs <<
"# " << getAnalysisType() <<
"\n";
375 ofs <<
"# OpenMD " << r.getFullRevision() <<
"\n";
376 ofs <<
"# " << r.getBuildDate() <<
"\n";
377 ofs <<
"# selection script1: \"" << selectionScript1_;
378 ofs <<
"\"\tselection script2: \"" << selectionScript2_ <<
"\"";
380 ofs <<
"\tselection script3: \"" << selectionScript3_ <<
"\"\n";
385 if (!paramString_.empty())
386 ofs <<
"# parameters: " << paramString_ <<
"\n";
388 for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
390 for (
unsigned int j = 0; j < avgGofr_[i].size(); ++j) {
392 for (
unsigned int k = 0; k < avgGofr_[i][j].size(); ++k) {
395 ofs << avgGofr_[i][j][k] / nProcessed_ <<
"\t";
403 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
404 "GofRAngle2: unable to open %s\n", outputFilename_.c_str());
405 painCave.isFatal = 1;
Radial Distribution Function.
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
void normalize()
Normalizes this vector in place.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
std::string getPrefix(const std::string &str)
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.