45#include "applications/staticProps/GofRAngle2.hpp"
52#include "types/MultipoleAdapter.hpp"
53#include "utils/Revision.hpp"
54#include "utils/simError.h"
58 GofRAngle2::GofRAngle2(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 setAnalysisType(
"Radial Distribution Function");
65 setOutputName(
getPrefix(filename) +
".grto");
67 deltaR_ = len_ / (double)nBins_;
68 deltaCosAngle_ = 2.0 / nAngleBins_;
70 std::stringstream params;
71 params <<
" nBins = " << nBins_ <<
", maxLen = " << len_
72 <<
", deltaR = " << deltaR_ <<
", nAngleBins = " << nAngleBins_
73 <<
", deltaCosAngle = " << deltaCosAngle_;
74 const std::string paramString = params.str();
75 setParameterString(paramString);
77 histogram_.resize(nBins_);
78 avgGofr_.resize(nBins_);
79 for (
unsigned int i = 0; i < nBins_; ++i) {
80 histogram_[i].resize(nAngleBins_);
81 avgGofr_[i].resize(nAngleBins_);
82 for (
unsigned int j = 0; j < nAngleBins_; ++j) {
83 histogram_[i][j].resize(nAngleBins_);
84 avgGofr_[i][j].resize(nAngleBins_);
89 GofRAngle2::GofRAngle2(SimInfo* info,
const std::string& filename,
90 const std::string& sele1,
const std::string& sele2,
91 const std::string& sele3, RealType len,
int nrbins,
93 RadialDistrFunc(info, filename, sele1, sele2, nrbins),
94 nAngleBins_(nangleBins), len_(len), doSele3_(true), seleMan3_(info),
95 evaluator3_(info), selectionScript3_(sele3) {
96 setOutputName(
getPrefix(filename) +
".grto");
98 deltaR_ = len_ / (double)nBins_;
99 deltaCosAngle_ = 2.0 / nAngleBins_;
101 std::stringstream params;
102 params <<
" nBins = " << nBins_ <<
", maxLen = " << len_
103 <<
", deltaR = " << deltaR_ <<
", nAngleBins = " << nAngleBins_
104 <<
", deltaCosAngle = " << deltaCosAngle_;
105 const std::string paramString = params.str();
106 setParameterString(paramString);
108 histogram_.resize(nBins_);
109 avgGofr_.resize(nBins_);
110 for (
unsigned int i = 0; i < nBins_; ++i) {
111 histogram_[i].resize(nAngleBins_);
112 avgGofr_[i].resize(nAngleBins_);
113 for (
unsigned int j = 0; j < nAngleBins_; ++j) {
114 histogram_[i][j].resize(nAngleBins_);
115 avgGofr_[i][j].resize(nAngleBins_);
119 evaluator3_.loadScriptString(sele3);
120 if (!evaluator3_.isDynamic()) {
121 seleMan3_.setSelectionSet(evaluator3_.evaluate());
125 void GofRAngle2::processNonOverlapping(SelectionManager& sman1,
126 SelectionManager& sman2) {
140 if (evaluator3_.isDynamic()) {
141 seleMan3_.setSelectionSet(evaluator3_.evaluate());
143 if (sman1.getSelectionCount() != seleMan3_.getSelectionCount()) {
144 RadialDistrFunc::processNonOverlapping(sman1, sman2);
147 for (sd1 = sman1.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
148 sd1 != NULL && sd3 != NULL;
149 sd1 = sman1.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
150 for (sd2 = sman2.beginSelected(j); sd2 != NULL;
151 sd2 = sman2.nextSelected(j)) {
152 collectHistogram(sd1, sd2, sd3);
156 RadialDistrFunc::processNonOverlapping(sman1, sman2);
160 void GofRAngle2::processOverlapping(SelectionManager& sman) {
174 if (evaluator3_.isDynamic()) {
175 seleMan3_.setSelectionSet(evaluator3_.evaluate());
177 if (sman.getSelectionCount() != seleMan3_.getSelectionCount()) {
178 RadialDistrFunc::processOverlapping(sman);
180 for (sd1 = sman.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
181 sd1 != NULL && sd3 != NULL;
182 sd1 = sman.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
183 for (j = i, sd2 = sman.nextSelected(j); sd2 != NULL;
184 sd2 = sman.nextSelected(j)) {
185 collectHistogram(sd1, sd2, sd3);
189 RadialDistrFunc::processOverlapping(sman);
193 void GofRAngle2::preProcess() {
194 for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
195 for (
unsigned int j = 0; j < avgGofr_[i].size(); ++j) {
196 std::fill(avgGofr_[i][j].begin(), avgGofr_[i][j].end(), 0.0);
201 void GofRAngle2::initializeHistogram() {
202 for (
unsigned int i = 0; i < histogram_.size(); ++i) {
203 for (
unsigned int j = 0; j < histogram_.size(); ++j) {
204 std::fill(histogram_[i][j].begin(), histogram_[i][j].end(), 0);
209 void GofRAngle2::processHistogram() {
210 int nPairs = getNPairs();
212 info_->getSnapshotManager()->getCurrentSnapshot()->getVolume();
213 RealType pairDensity = nPairs / volume;
214 RealType pairConstant = (4.0 * Constants::PI * pairDensity) /
215 (3.0 * (
double)nAngleBins_ * (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 for (
unsigned int k = 0; k < histogram_[i][j].size(); ++k) {
226 avgGofr_[i][j][k] += RealType(histogram_[i][j][k]) / nIdeal;
232 void GofRAngle2::collectHistogram(StuntDouble* sd1, StuntDouble* sd2) {
233 bool usePeriodicBoundaryConditions_ =
234 info_->getSimParams()->getUsePeriodicBoundaryConditions();
236 if (sd1 == sd2) {
return; }
238 Vector3d pos1 = sd1->getPos();
239 Vector3d pos2 = sd2->getPos();
240 Vector3d r12 = pos1 - pos2;
241 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
244 int whichRBin = int(distance / deltaR_);
246 if (distance <= len_) {
247 if (!sd1->isDirectional()) {
248 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
249 "GofAngle2: attempted to use a non-directional object: %s\n",
250 sd1->getType().c_str());
251 painCave.isFatal = 1;
255 if (!sd2->isDirectional()) {
256 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
257 "GofAngle2: attempted to use a non-directional object: %s\n",
258 sd2->getType().c_str());
259 painCave.isFatal = 1;
263 Vector3d dipole1, dipole2;
266 AtomType* atype1 =
static_cast<Atom*
>(sd1)->getAtomType();
267 MultipoleAdapter ma1 = MultipoleAdapter(atype1);
269 dipole1 = sd1->getDipole();
271 dipole1 = sd1->getA().transpose() * V3Z;
274 dipole1 = sd1->getA().transpose() * V3Z;
278 AtomType* atype2 =
static_cast<Atom*
>(sd2)->getAtomType();
279 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
281 dipole2 = sd2->getDipole();
283 dipole2 = sd2->getA().transpose() * V3Z;
285 dipole2 = sd2->getA().transpose() * V3Z;
292 RealType cosAngle1 =
dot(r12, dipole1);
293 RealType cosAngle2 =
dot(dipole1, dipole2);
295 RealType halfBin = (nAngleBins_ - 1) * 0.5;
296 int angleBin1 = int(halfBin * (cosAngle1 + 1.0));
297 int angleBin2 = int(halfBin * (cosAngle2 + 1.0));
299 ++histogram_[whichRBin][angleBin1][angleBin2];
303 void GofRAngle2::collectHistogram(StuntDouble* sd1, StuntDouble* sd2,
305 bool usePeriodicBoundaryConditions_ =
306 info_->getSimParams()->getUsePeriodicBoundaryConditions();
308 if (sd1 == sd2) {
return; }
310 Vector3d p1 = sd1->getPos();
311 Vector3d p3 = sd3->getPos();
313 Vector3d c = 0.5 * (p1 + p3);
314 Vector3d r13 = p3 - p1;
316 Vector3d r12 = sd2->getPos() - c;
318 if (usePeriodicBoundaryConditions_) {
319 currentSnapshot_->wrapVector(r12);
320 currentSnapshot_->wrapVector(r13);
324 int whichRBin = int(distance / deltaR_);
326 if (distance <= len_) {
330 if (!sd2->isDirectional()) {
331 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
332 "GofAngle2: attempted to use a non-directional object: %s\n",
333 sd2->getType().c_str());
334 painCave.isFatal = 1;
341 AtomType* atype2 =
static_cast<Atom*
>(sd2)->getAtomType();
342 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
345 dipole2 = sd2->getDipole();
347 dipole2 = sd2->getA().transpose() * V3Z;
351 dipole2 = sd2->getA().transpose() * V3Z;
356 RealType cosAngle1 =
dot(r12, r13);
357 RealType cosAngle2 =
dot(r13, dipole2);
359 RealType halfBin = (nAngleBins_ - 1) * 0.5;
360 int angleBin1 = int(halfBin * (cosAngle1 + 1.0));
361 int angleBin2 = int(halfBin * (cosAngle2 + 1.0));
363 ++histogram_[whichRBin][angleBin1][angleBin2];
367 void GofRAngle2::writeRdf() {
368 std::ofstream ofs(outputFilename_.c_str());
371 ofs <<
"# " << getAnalysisType() <<
"\n";
372 ofs <<
"# OpenMD " << r.getFullRevision() <<
"\n";
373 ofs <<
"# " << r.getBuildDate() <<
"\n";
374 ofs <<
"# selection script1: \"" << selectionScript1_;
375 ofs <<
"\"\tselection script2: \"" << selectionScript2_ <<
"\"";
377 ofs <<
"\tselection script3: \"" << selectionScript3_ <<
"\"\n";
382 if (!paramString_.empty())
383 ofs <<
"# parameters: " << paramString_ <<
"\n";
385 for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
387 for (
unsigned int j = 0; j < avgGofr_[i].size(); ++j) {
389 for (
unsigned int k = 0; k < avgGofr_[i][j].size(); ++k) {
392 ofs << avgGofr_[i][j][k] / nProcessed_ <<
"\t";
400 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
401 "GofRAngle2: unable to open %s\n", outputFilename_.c_str());
402 painCave.isFatal = 1;
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.