48#include "applications/staticProps/GofRAngle.hpp"
55#include "types/MultipoleAdapter.hpp"
56#include "utils/Revision.hpp"
57#include "utils/simError.h"
61 GofRAngle::GofRAngle(
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 deltaR_ = len_ / (double)nBins_;
68 deltaCosAngle_ = 2.0 / (double)nAngleBins_;
69 histogram_.resize(nBins_);
70 avgGofr_.resize(nBins_);
71 for (
unsigned int i = 0; i < nBins_; ++i) {
72 histogram_[i].resize(nAngleBins_);
73 avgGofr_[i].resize(nAngleBins_);
76 setAnalysisType(
"Radial Distribution Function");
78 std::stringstream params;
79 params <<
" nBins = " << nBins_ <<
", maxLen = " << len_
80 <<
", deltaR = " << deltaR_ <<
", nAngleBins = " << nAngleBins_
81 <<
", deltaCosAngle = " << deltaCosAngle_;
82 const std::string paramString = params.str();
83 setParameterString(paramString);
86 GofRAngle::GofRAngle(SimInfo* info,
const std::string& filename,
87 const std::string& sele1,
const std::string& sele2,
88 const std::string& sele3, RealType len,
int nrbins,
90 RadialDistrFunc(info, filename, sele1, sele2, nrbins),
91 nAngleBins_(nangleBins), len_(len), doSele3_(true),
92 selectionScript3_(sele3), seleMan3_(info), evaluator3_(info) {
93 deltaR_ = len_ / (double)nBins_;
94 deltaCosAngle_ = 2.0 / (double)nAngleBins_;
95 histogram_.resize(nBins_);
96 avgGofr_.resize(nBins_);
97 for (
unsigned int i = 0; i < nBins_; ++i) {
98 histogram_[i].resize(nAngleBins_);
99 avgGofr_[i].resize(nAngleBins_);
102 evaluator3_.loadScriptString(sele3);
103 if (!evaluator3_.isDynamic()) {
104 seleMan3_.setSelectionSet(evaluator3_.evaluate());
108 void GofRAngle::processNonOverlapping(SelectionManager& sman1,
109 SelectionManager& sman2) {
123 if (evaluator3_.isDynamic()) {
124 seleMan3_.setSelectionSet(evaluator3_.evaluate());
126 if (sman1.getSelectionCount() != seleMan3_.getSelectionCount()) {
127 RadialDistrFunc::processNonOverlapping(sman1, sman2);
130 for (sd1 = sman1.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
131 sd1 != NULL && sd3 != NULL;
132 sd1 = sman1.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
133 for (sd2 = sman2.beginSelected(j); sd2 != NULL;
134 sd2 = sman2.nextSelected(j)) {
135 collectHistogram(sd1, sd2, sd3);
139 RadialDistrFunc::processNonOverlapping(sman1, sman2);
143 void GofRAngle::processOverlapping(SelectionManager& sman) {
157 if (evaluator3_.isDynamic()) {
158 seleMan3_.setSelectionSet(evaluator3_.evaluate());
160 if (sman.getSelectionCount() != seleMan3_.getSelectionCount()) {
161 RadialDistrFunc::processOverlapping(sman);
163 for (sd1 = sman.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
164 sd1 != NULL && sd3 != NULL;
165 sd1 = sman.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
166 for (j = i, sd2 = sman.nextSelected(j); sd2 != NULL;
167 sd2 = sman.nextSelected(j)) {
168 collectHistogram(sd1, sd2, sd3);
172 RadialDistrFunc::processOverlapping(sman);
176 void GofRAngle::preProcess() {
177 for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
178 std::fill(avgGofr_[i].begin(), avgGofr_[i].end(), 0);
182 void GofRAngle::initializeHistogram() {
184 for (
unsigned int i = 0; i < histogram_.size(); ++i) {
185 std::fill(histogram_[i].begin(), histogram_[i].end(), 0);
189 void GofRAngle::processHistogram() {
190 int nPairs = getNPairs();
192 info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
193 RealType pairDensity = nPairs / volume;
194 RealType pairConstant = (4.0 * Constants::PI * pairDensity) / 3.0;
196 for (
unsigned int i = 0; i < histogram_.size(); ++i) {
197 RealType rLower = i * deltaR_;
198 RealType rUpper = rLower + deltaR_;
200 (rUpper * rUpper * rUpper) - (rLower * rLower * rLower);
201 RealType nIdeal = volSlice * pairConstant;
203 for (
unsigned int j = 0; j < histogram_[i].size(); ++j) {
204 avgGofr_[i][j] += histogram_[i][j] / nIdeal;
209 void GofRTheta::processHistogram() {
210 int nPairs = getNPairs();
212 info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
213 RealType pairDensity = nPairs / volume;
214 RealType pairConstant =
215 (4.0 * Constants::PI * pairDensity) / (3.0 * (
double)nAngleBins_);
217 for (
unsigned int i = 0; i < histogram_.size(); ++i) {
218 RealType rLower = i * deltaR_;
219 RealType rUpper = rLower + deltaR_;
221 (rUpper * rUpper * rUpper) - (rLower * rLower * rLower);
222 RealType nIdeal = volSlice * pairConstant;
224 for (
unsigned int j = 0; j < histogram_[i].size(); ++j) {
225 avgGofr_[i][j] += histogram_[i][j] / nIdeal;
230 void GofRAngle::collectHistogram(StuntDouble* sd1, StuntDouble* sd2) {
231 if (sd1 == sd2) {
return; }
232 bool usePeriodicBoundaryConditions_ =
233 info_->getSimParams()->getUsePeriodicBoundaryConditions();
235 Vector3d pos1 = sd1->getPos();
236 Vector3d pos2 = sd2->getPos();
237 Vector3d r12 = pos2 - pos1;
238 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
241 int whichRBin = int(distance / deltaR_);
243 if (distance <= len_) {
244 RealType cosAngle = evaluateAngle(sd1, sd2);
245 RealType halfBin = (nAngleBins_ - 1) * 0.5;
246 int whichThetaBin = int(halfBin * (cosAngle + 1.0));
247 ++histogram_[whichRBin][whichThetaBin];
253 void GofRAngle::collectHistogram(StuntDouble* sd1, StuntDouble* sd2,
255 if (sd1 == sd2) {
return; }
256 bool usePeriodicBoundaryConditions_ =
257 info_->getSimParams()->getUsePeriodicBoundaryConditions();
259 Vector3d p1 = sd1->getPos();
260 Vector3d p3 = sd3->getPos();
262 Vector3d c = 0.5 * (p1 + p3);
263 Vector3d r13 = p3 - p1;
265 Vector3d r12 = sd2->getPos() - c;
267 if (usePeriodicBoundaryConditions_) {
268 currentSnapshot_->wrapVector(r12);
269 currentSnapshot_->wrapVector(r13);
273 int whichRBin = int(distance / deltaR_);
275 if (distance <= len_) {
276 RealType cosAngle = evaluateAngle(sd1, sd2, sd3);
277 RealType halfBin = (nAngleBins_ - 1) * 0.5;
278 int whichThetaBin = int(halfBin * (cosAngle + 1.0));
279 ++histogram_[whichRBin][whichThetaBin];
285 void GofRAngle::writeRdf() {
286 std::ofstream ofs(outputFilename_.c_str());
289 ofs <<
"# " << getAnalysisType() <<
"\n";
290 ofs <<
"# OpenMD " << r.getFullRevision() <<
"\n";
291 ofs <<
"# " << r.getBuildDate() <<
"\n";
292 ofs <<
"# selection script1: \"" << selectionScript1_;
293 ofs <<
"\"\tselection script2: \"" << selectionScript2_ <<
"\"";
295 ofs <<
"\tselection script3: \"" << selectionScript3_ <<
"\"\n";
300 if (!paramString_.empty())
301 ofs <<
"# parameters: " << paramString_ <<
"\n";
303 for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
306 for (
unsigned int j = 0; j < avgGofr_[i].size(); ++j) {
308 ofs << avgGofr_[i][j] / nProcessed_ <<
"\t";
315 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
316 "GofRAngle: unable to open %s\n", outputFilename_.c_str());
317 painCave.isFatal = 1;
324 RealType GofRTheta::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2) {
325 bool usePeriodicBoundaryConditions_ =
326 info_->getSimParams()->getUsePeriodicBoundaryConditions();
328 Vector3d pos1 = sd1->getPos();
329 Vector3d pos2 = sd2->getPos();
330 Vector3d r12 = pos2 - pos1;
332 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
338 if (!sd1->isDirectional()) {
339 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
340 "GofRTheta: attempted to use a non-directional object: %s\n",
341 sd1->getType().c_str());
342 painCave.isFatal = 1;
347 AtomType* atype1 =
static_cast<Atom*
>(sd1)->getAtomType();
348 MultipoleAdapter ma1 = MultipoleAdapter(atype1);
351 vec = sd1->getDipole();
353 vec = sd1->getA().transpose() * V3Z;
355 vec = sd1->getA().transpose() * V3Z;
360 return dot(r12, vec);
363 RealType GofRTheta::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2,
365 bool usePeriodicBoundaryConditions_ =
366 info_->getSimParams()->getUsePeriodicBoundaryConditions();
368 Vector3d p1 = sd1->getPos();
369 Vector3d p3 = sd3->getPos();
371 Vector3d c = 0.5 * (p1 + p3);
372 Vector3d r13 = p3 - p1;
374 Vector3d r12 = sd2->getPos() - c;
376 if (usePeriodicBoundaryConditions_) {
377 currentSnapshot_->wrapVector(r12);
378 currentSnapshot_->wrapVector(r13);
384 return dot(r12, r13);
387 RealType GofROmega::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2) {
390 if (!sd1->isDirectional()) {
391 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
392 "GofROmega: attempted to use a non-directional object: %s\n",
393 sd1->getType().c_str());
394 painCave.isFatal = 1;
399 AtomType* atype1 =
static_cast<Atom*
>(sd1)->getAtomType();
400 MultipoleAdapter ma1 = MultipoleAdapter(atype1);
402 v1 = sd1->getDipole();
404 v1 = sd1->getA().transpose() * V3Z;
406 v1 = sd1->getA().transpose() * V3Z;
409 if (!sd2->isDirectional()) {
410 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
411 "GofROmega attempted to use a non-directional object: %s\n",
412 sd2->getType().c_str());
413 painCave.isFatal = 1;
418 AtomType* atype2 =
static_cast<Atom*
>(sd2)->getAtomType();
419 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
422 v2 = sd2->getDipole();
424 v2 = sd2->getA().transpose() * V3Z;
426 v2 = sd2->getA().transpose() * V3Z;
434 RealType GofROmega::evaluateAngle(StuntDouble* sd1, StuntDouble* sd2,
436 bool usePeriodicBoundaryConditions_ =
437 info_->getSimParams()->getUsePeriodicBoundaryConditions();
442 v1 = sd3->getPos() - sd1->getPos();
443 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(v1);
445 if (!sd2->isDirectional()) {
446 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
447 "GofROmega: attempted to use a non-directional object: %s\n",
448 sd2->getType().c_str());
449 painCave.isFatal = 1;
454 AtomType* atype2 =
static_cast<Atom*
>(sd2)->getAtomType();
455 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
458 v2 = sd2->getDipole();
460 v2 = sd2->getA().transpose() * V3Z;
462 v2 = sd2->getA().transpose() * V3Z;
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.
Real distance(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the distance between two DynamicVectors.