45#include "applications/staticProps/GofAngle2.hpp"
52#include "types/MultipoleAdapter.hpp"
53#include "utils/Revision.hpp"
54#include "utils/simError.h"
58 GofAngle2::GofAngle2(SimInfo* info,
const std::string& filename,
59 const std::string& sele1,
const std::string& sele2,
61 RadialDistrFunc(info, filename, sele1, sele2, nangleBins),
62 doSele3_(false), seleMan3_(info), evaluator3_(info) {
63 setAnalysisType(
"Radial Distribution Function");
64 setOutputName(
getPrefix(filename) +
".gto");
66 deltaCosAngle_ = 2.0 / nBins_;
68 std::stringstream params;
69 params <<
" nAngleBins = " << nBins_
70 <<
", deltaCosAngle = " << deltaCosAngle_;
71 const std::string paramString = params.str();
72 setParameterString(paramString);
74 histogram_.resize(nBins_);
75 avgGofr_.resize(nBins_);
76 for (
unsigned int i = 0; i < nBins_; ++i) {
77 histogram_[i].resize(nBins_);
78 avgGofr_[i].resize(nBins_);
82 GofAngle2::GofAngle2(SimInfo* info,
const std::string& filename,
83 const std::string& sele1,
const std::string& sele2,
84 const std::string& sele3,
int nangleBins) :
85 RadialDistrFunc(info, filename, sele1, sele2, nangleBins),
86 doSele3_(true), seleMan3_(info), evaluator3_(info),
87 selectionScript3_(sele3) {
88 setOutputName(
getPrefix(filename) +
".gto");
90 deltaCosAngle_ = 2.0 / nBins_;
92 histogram_.resize(nBins_);
93 avgGofr_.resize(nBins_);
94 for (
unsigned int i = 0; i < nBins_; ++i) {
95 histogram_[i].resize(nBins_);
96 avgGofr_[i].resize(nBins_);
98 evaluator3_.loadScriptString(sele3);
99 if (!evaluator3_.isDynamic()) {
100 seleMan3_.setSelectionSet(evaluator3_.evaluate());
104 void GofAngle2::processNonOverlapping(SelectionManager& sman1,
105 SelectionManager& sman2) {
119 if (evaluator3_.isDynamic()) {
120 seleMan3_.setSelectionSet(evaluator3_.evaluate());
122 if (sman1.getSelectionCount() != seleMan3_.getSelectionCount()) {
123 RadialDistrFunc::processNonOverlapping(sman1, sman2);
126 for (sd1 = sman1.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
127 sd1 != NULL && sd3 != NULL;
128 sd1 = sman1.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
129 for (sd2 = sman2.beginSelected(j); sd2 != NULL;
130 sd2 = sman2.nextSelected(j)) {
131 collectHistogram(sd1, sd2, sd3);
135 RadialDistrFunc::processNonOverlapping(sman1, sman2);
139 void GofAngle2::processOverlapping(SelectionManager& sman) {
153 if (evaluator3_.isDynamic()) {
154 seleMan3_.setSelectionSet(evaluator3_.evaluate());
156 if (sman.getSelectionCount() != seleMan3_.getSelectionCount()) {
157 RadialDistrFunc::processOverlapping(sman);
159 for (sd1 = sman.beginSelected(i), sd3 = seleMan3_.beginSelected(k);
160 sd1 != NULL && sd3 != NULL;
161 sd1 = sman.nextSelected(i), sd3 = seleMan3_.nextSelected(k)) {
162 for (j = i, sd2 = sman.nextSelected(j); sd2 != NULL;
163 sd2 = sman.nextSelected(j)) {
164 collectHistogram(sd1, sd2, sd3);
168 RadialDistrFunc::processOverlapping(sman);
172 void GofAngle2::preProcess() {
173 for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
174 std::fill(avgGofr_[i].begin(), avgGofr_[i].end(), 0);
178 void GofAngle2::initializeHistogram() {
180 for (
unsigned int i = 0; i < histogram_.size(); ++i)
181 std::fill(histogram_[i].begin(), histogram_[i].end(), 0);
184 void GofAngle2::processHistogram() {
189 void GofAngle2::collectHistogram(StuntDouble* sd1, StuntDouble* sd2) {
190 bool usePeriodicBoundaryConditions_ =
191 info_->getSimParams()->getUsePeriodicBoundaryConditions();
193 if (sd1 == sd2) {
return; }
195 Vector3d pos1 = sd1->getPos();
196 Vector3d pos2 = sd2->getPos();
197 Vector3d r12 = pos1 - pos2;
198 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(r12);
200 AtomType* atype1 =
static_cast<Atom*
>(sd1)->getAtomType();
201 AtomType* atype2 =
static_cast<Atom*
>(sd2)->getAtomType();
202 MultipoleAdapter ma1 = MultipoleAdapter(atype1);
203 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
205 if (!sd1->isDirectional()) {
206 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
207 "GofAngle2: attempted to use a non-directional object: %s\n",
208 sd1->getType().c_str());
209 painCave.isFatal = 1;
213 if (!sd2->isDirectional()) {
214 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
215 "GofAngle2: attempted to use a non-directional object: %s\n",
216 sd2->getType().c_str());
217 painCave.isFatal = 1;
221 Vector3d dipole1, dipole2;
223 dipole1 = sd1->getDipole();
225 dipole1 = sd1->getA().transpose() * V3Z;
228 dipole2 = sd2->getDipole();
230 dipole2 = sd2->getA().transpose() * V3Z;
236 RealType cosAngle1 =
dot(r12, dipole1);
237 RealType cosAngle2 =
dot(dipole1, dipole2);
239 RealType halfBin = (nBins_ - 1) * 0.5;
240 int angleBin1 = int(halfBin * (cosAngle1 + 1.0));
241 int angleBin2 = int(halfBin * (cosAngle2 + 1.0));
243 ++histogram_[angleBin1][angleBin2];
247 void GofAngle2::collectHistogram(StuntDouble* sd1, StuntDouble* sd2,
249 bool usePeriodicBoundaryConditions_ =
250 info_->getSimParams()->getUsePeriodicBoundaryConditions();
252 if (sd1 == sd2) {
return; }
254 Vector3d p1 = sd1->getPos();
255 Vector3d p3 = sd3->getPos();
257 Vector3d c = 0.5 * (p1 + p3);
258 Vector3d r13 = p3 - p1;
260 Vector3d r12 = sd2->getPos() - c;
262 if (usePeriodicBoundaryConditions_) {
263 currentSnapshot_->wrapVector(r12);
264 currentSnapshot_->wrapVector(r13);
269 if (!sd2->isDirectional()) {
270 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
271 "GofAngle2: attempted to use a non-directional object: %s\n",
272 sd2->getType().c_str());
273 painCave.isFatal = 1;
277 AtomType* atype2 =
static_cast<Atom*
>(sd2)->getAtomType();
278 MultipoleAdapter ma2 = MultipoleAdapter(atype2);
282 dipole2 = sd2->getDipole();
284 dipole2 = sd2->getA().transpose() * V3Z;
288 RealType cosAngle1 =
dot(r12, r13);
289 RealType cosAngle2 =
dot(r13, dipole2);
291 RealType halfBin = (nBins_ - 1) * 0.5;
292 int angleBin1 = int(halfBin * (cosAngle1 + 1.0));
293 int angleBin2 = int(halfBin * (cosAngle2 + 1.0));
295 ++histogram_[angleBin1][angleBin2];
299 void GofAngle2::writeRdf() {
300 std::ofstream ofs(outputFilename_.c_str());
303 ofs <<
"# " << getAnalysisType() <<
"\n";
304 ofs <<
"# OpenMD " << r.getFullRevision() <<
"\n";
305 ofs <<
"# " << r.getBuildDate() <<
"\n";
306 ofs <<
"# selection script1: \"" << selectionScript1_;
307 ofs <<
"\"\tselection script2: \"" << selectionScript2_ <<
"\"";
309 ofs <<
"\tselection script3: \"" << selectionScript3_ <<
"\"\n";
314 if (!paramString_.empty())
315 ofs <<
"# parameters: " << paramString_ <<
"\n";
317 for (
unsigned int i = 0; i < avgGofr_.size(); ++i) {
320 for (
unsigned int j = 0; j < avgGofr_[i].size(); ++j) {
322 ofs << avgGofr_[i][j] / nProcessed_ <<
"\t";
328 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
329 "GofAngle2: unable to open %s\n", outputFilename_.c_str());
330 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)