45#include "applications/staticProps/GofRAngle.hpp"
52#include "types/MultipoleAdapter.hpp"
53#include "utils/Revision.hpp"
54#include "utils/simError.h"
58 GofRAngle::GofRAngle(SimInfo* info,
const std::string& filename,
59 const std::string& sele1,
const std::string& sele2,
60 RealType len,
int nrbins,
int nangleBins) :
61 RadialDistrFunc(info, filename, sele1, sele2, nrbins),
62 nAngleBins_(nangleBins), len_(len), doSele3_(false), seleMan3_(info),
64 deltaR_ = len_ / (double)nBins_;
65 deltaCosAngle_ = 2.0 / (double)nAngleBins_;
66 histogram_.resize(nBins_);
67 avgGofr_.resize(nBins_);
68 for (
unsigned int i = 0; i < nBins_; ++i) {
69 histogram_[i].resize(nAngleBins_);
70 avgGofr_[i].resize(nAngleBins_);
73 setAnalysisType(
"Radial Distribution Function");
75 std::stringstream params;
76 params <<
" nBins = " << nBins_ <<
", maxLen = " << len_
77 <<
", deltaR = " << deltaR_ <<
", nAngleBins = " << nAngleBins_
78 <<
", deltaCosAngle = " << deltaCosAngle_;
79 const std::string paramString = params.str();
80 setParameterString(paramString);
83 GofRAngle::GofRAngle(SimInfo* info,
const std::string& filename,
84 const std::string& sele1,
const std::string& sele2,
85 const std::string& sele3, RealType len,
int nrbins,
87 RadialDistrFunc(info, filename, sele1, sele2, nrbins),
88 nAngleBins_(nangleBins), len_(len), doSele3_(true),
89 selectionScript3_(sele3), seleMan3_(info), evaluator3_(info) {
90 deltaR_ = len_ / (double)nBins_;
91 deltaCosAngle_ = 2.0 / (double)nAngleBins_;
92 histogram_.resize(nBins_);
93 avgGofr_.resize(nBins_);
94 for (
unsigned int i = 0; i < nBins_; ++i) {
95 histogram_[i].resize(nAngleBins_);
96 avgGofr_[i].resize(nAngleBins_);
99 evaluator3_.loadScriptString(sele3);
100 if (!evaluator3_.isDynamic()) {
101 seleMan3_.setSelectionSet(evaluator3_.evaluate());
105 void GofRAngle::processNonOverlapping(SelectionManager& sman1,
106 SelectionManager& sman2) {
120 if (evaluator3_.isDynamic()) {
121 seleMan3_.setSelectionSet(evaluator3_.evaluate());
123 if (sman1.getSelectionCount() != seleMan3_.getSelectionCount()) {
124 RadialDistrFunc::processNonOverlapping(sman1, sman2);
127 for (sd1 = sman1.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
128 sd1 != NULL && sd3 != NULL;
129 sd1 = sman1.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
130 for (sd2 = sman2.beginSelected(j); sd2 != NULL;
131 sd2 = sman2.nextSelected(j)) {
132 collectHistogram(sd1, sd2, sd3);
136 RadialDistrFunc::processNonOverlapping(sman1, sman2);
140 void GofRAngle::processOverlapping(SelectionManager& sman) {
154 if (evaluator3_.isDynamic()) {
155 seleMan3_.setSelectionSet(evaluator3_.evaluate());
157 if (sman.getSelectionCount() != seleMan3_.getSelectionCount()) {
158 RadialDistrFunc::processOverlapping(sman);
160 for (sd1 = sman.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
161 sd1 != NULL && sd3 != NULL;
162 sd1 = sman.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
163 for (j = i, sd2 = sman.nextSelected(j); sd2 != NULL;
164 sd2 = sman.nextSelected(j)) {
165 collectHistogram(sd1, sd2, sd3);
169 RadialDistrFunc::processOverlapping(sman);
173 void GofRAngle::preProcess() {
174 for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
175 std::fill(avgGofr_[i].begin(), avgGofr_[i].end(), 0);
179 void GofRAngle::initializeHistogram() {
181 for (
unsigned int i = 0; i < histogram_.size(); ++i) {
182 std::fill(histogram_[i].begin(), histogram_[i].end(), 0);
186 void GofRAngle::processHistogram() {
187 int nPairs = getNPairs();
189 info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
190 RealType pairDensity = nPairs / volume;
191 RealType pairConstant = (4.0 * Constants::PI * pairDensity) / 3.0;
193 for (
unsigned int i = 0; i < histogram_.size(); ++i) {
194 RealType rLower = i * deltaR_;
195 RealType rUpper = rLower + deltaR_;
197 (rUpper * rUpper * rUpper) - (rLower * rLower * rLower);
198 RealType nIdeal = volSlice * pairConstant;
200 for (
unsigned int j = 0; j < histogram_[i].size(); ++j) {
201 avgGofr_[i][j] += histogram_[i][j] / nIdeal;
206 void GofRTheta::processHistogram() {
207 int nPairs = getNPairs();
209 info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
210 RealType pairDensity = nPairs / volume;
211 RealType pairConstant =
212 (4.0 * Constants::PI * pairDensity) / (3.0 * (
double)nAngleBins_);
214 for (
unsigned int i = 0; i < histogram_.size(); ++i) {
215 RealType rLower = i * deltaR_;
216 RealType rUpper = rLower + deltaR_;
218 (rUpper * rUpper * rUpper) - (rLower * rLower * rLower);
219 RealType nIdeal = volSlice * pairConstant;
221 for (
unsigned int j = 0; j < histogram_[i].size(); ++j) {
222 avgGofr_[i][j] += histogram_[i][j] / nIdeal;
227 void GofRAngle::collectHistogram(StuntDouble* sd1, StuntDouble* sd2) {
228 if (sd1 == sd2) {
return; }
229 bool usePeriodicBoundaryConditions_ =
230 info_->getSimParams()->getUsePeriodicBoundaryConditions();
232 Vector3d pos1 = sd1->getPos();
233 Vector3d pos2 = sd2->getPos();
234 Vector3d r12 = pos2 - pos1;
235 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
238 int whichRBin = int(distance / deltaR_);
240 if (distance <= len_) {
241 RealType cosAngle = evaluateAngle(sd1, sd2);
242 RealType halfBin = (nAngleBins_ - 1) * 0.5;
243 int whichThetaBin = int(halfBin * (cosAngle + 1.0));
244 ++histogram_[whichRBin][whichThetaBin];
250 void GofRAngle::collectHistogram(StuntDouble* sd1, StuntDouble* sd2,
252 if (sd1 == sd2) {
return; }
253 bool usePeriodicBoundaryConditions_ =
254 info_->getSimParams()->getUsePeriodicBoundaryConditions();
256 Vector3d p1 = sd1->getPos();
257 Vector3d p3 = sd3->getPos();
259 Vector3d c = 0.5 * (p1 + p3);
260 Vector3d r13 = p3 - p1;
262 Vector3d r12 = sd2->getPos() - c;
264 if (usePeriodicBoundaryConditions_) {
265 currentSnapshot_->wrapVector(r12);
266 currentSnapshot_->wrapVector(r13);
270 int whichRBin = int(distance / deltaR_);
272 if (distance <= len_) {
273 RealType cosAngle = evaluateAngle(sd1, sd2, sd3);
274 RealType halfBin = (nAngleBins_ - 1) * 0.5;
275 int whichThetaBin = int(halfBin * (cosAngle + 1.0));
276 ++histogram_[whichRBin][whichThetaBin];
282 void GofRAngle::writeRdf() {
283 std::ofstream ofs(outputFilename_.c_str());
286 ofs <<
"# " << getAnalysisType() <<
"\n";
287 ofs <<
"# OpenMD " << r.getFullRevision() <<
"\n";
288 ofs <<
"# " << r.getBuildDate() <<
"\n";
289 ofs <<
"# selection script1: \"" << selectionScript1_;
290 ofs <<
"\"\tselection script2: \"" << selectionScript2_ <<
"\"";
292 ofs <<
"\tselection script3: \"" << selectionScript3_ <<
"\"\n";
297 if (!paramString_.empty())
298 ofs <<
"# parameters: " << paramString_ <<
"\n";
300 for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
303 for (
unsigned int j = 0; j < avgGofr_[i].size(); ++j) {
305 ofs << avgGofr_[i][j] / nProcessed_ <<
"\t";
312 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
313 "GofRAngle: unable to open %s\n", outputFilename_.c_str());
314 painCave.isFatal = 1;
321 RealType GofRTheta::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2) {
322 bool usePeriodicBoundaryConditions_ =
323 info_->getSimParams()->getUsePeriodicBoundaryConditions();
325 Vector3d pos1 = sd1->getPos();
326 Vector3d pos2 = sd2->getPos();
327 Vector3d r12 = pos2 - pos1;
329 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
335 if (!sd1->isDirectional()) {
336 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
337 "GofRTheta: attempted to use a non-directional object: %s\n",
338 sd1->getType().c_str());
339 painCave.isFatal = 1;
344 AtomType* atype1 =
static_cast<Atom*
>(sd1)->getAtomType();
345 MultipoleAdapter ma1 = MultipoleAdapter(atype1);
348 vec = sd1->getDipole();
350 vec = sd1->getA().transpose() * V3Z;
352 vec = sd1->getA().transpose() * V3Z;
357 return dot(r12, vec);
360 RealType GofRTheta::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2,
362 bool usePeriodicBoundaryConditions_ =
363 info_->getSimParams()->getUsePeriodicBoundaryConditions();
365 Vector3d p1 = sd1->getPos();
366 Vector3d p3 = sd3->getPos();
368 Vector3d c = 0.5 * (p1 + p3);
369 Vector3d r13 = p3 - p1;
371 Vector3d r12 = sd2->getPos() - c;
373 if (usePeriodicBoundaryConditions_) {
374 currentSnapshot_->wrapVector(r12);
375 currentSnapshot_->wrapVector(r13);
381 return dot(r12, r13);
384 RealType GofROmega::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2) {
387 if (!sd1->isDirectional()) {
388 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
389 "GofROmega: attempted to use a non-directional object: %s\n",
390 sd1->getType().c_str());
391 painCave.isFatal = 1;
396 AtomType* atype1 =
static_cast<Atom*
>(sd1)->getAtomType();
397 MultipoleAdapter ma1 = MultipoleAdapter(atype1);
399 v1 = sd1->getDipole();
401 v1 = sd1->getA().transpose() * V3Z;
403 v1 = sd1->getA().transpose() * V3Z;
406 if (!sd2->isDirectional()) {
407 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
408 "GofROmega attempted to use a non-directional object: %s\n",
409 sd2->getType().c_str());
410 painCave.isFatal = 1;
415 AtomType* atype2 =
static_cast<Atom*
>(sd2)->getAtomType();
416 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
419 v2 = sd2->getDipole();
421 v2 = sd2->getA().transpose() * V3Z;
423 v2 = sd2->getA().transpose() * V3Z;
431 RealType GofROmega::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2,
433 bool usePeriodicBoundaryConditions_ =
434 info_->getSimParams()->getUsePeriodicBoundaryConditions();
439 v1 = sd3->getPos() - sd1->getPos();
440 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(v1);
442 if (!sd2->isDirectional()) {
443 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
444 "GofROmega: attempted to use a non-directional object: %s\n",
445 sd2->getType().c_str());
446 painCave.isFatal = 1;
451 AtomType* atype2 =
static_cast<Atom*
>(sd2)->getAtomType();
452 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
455 v2 = sd2->getDipole();
457 v2 = sd2->getA().transpose() * V3Z;
459 v2 = sd2->getA().transpose() * V3Z;
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.
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.