45#include "applications/staticProps/TetrahedralityHBMatrix.hpp"
51#include "utils/Constants.hpp"
52#include "utils/Revision.hpp"
53#include "utils/simError.h"
57 TetrahedralityHBMatrix::TetrahedralityHBMatrix(
58 SimInfo* info,
const std::string& filename,
const std::string& sele,
59 double rCut,
double OOcut,
double thetaCut,
double OHcut,
int nbins) :
60 StaticAnalyser(info, filename, nbins),
61 selectionScript_(sele), seleMan_(info), evaluator_(info), rCut_(rCut),
62 OOCut_(OOcut), thetaCut_(thetaCut), OHCut_(OHcut) {
63 setAnalysisType(
"Tetrahedrality HBond Matrix");
64 setOutputName(
getPrefix(filename) +
".hbq");
66 evaluator_.loadScriptString(sele);
67 if (!evaluator_.isDynamic()) {
68 seleMan_.setSelectionSet(evaluator_.evaluate());
71 Q_histogram_.resize(nBins_);
73 for (
unsigned int i = 0; i < nBins_; i++) {
74 Q_histogram_[i].resize(nBins_);
81 deltaQ_ = (MaxQ_ - MinQ_) / nBins_;
83 std::stringstream params;
84 params <<
" rCut = " << rCut_ <<
", OOcut = " << OOCut_
85 <<
", thetacut = " << thetaCut_ <<
", OHcut = " << OHCut_
86 <<
", nbins = " << nBins_ <<
", deltaQ = " << deltaQ_;
87 const std::string paramString = params.str();
88 setParameterString(paramString);
91 void TetrahedralityHBMatrix::initializeHistogram() {
92 for (
unsigned int i = 0; i < nBins_; i++) {
93 std::fill(Q_histogram_[i].begin(), Q_histogram_[i].end(), 0);
97 void TetrahedralityHBMatrix::process() {
102 SimInfo::MoleculeIterator mi;
104 Vector3d ri, rj, rk, rik, rkj, dposition, tposition;
106 std::vector<Molecule::HBondDonor*>::iterator hbdi;
107 Molecule::HBondDonor* hbd;
108 std::vector<Atom*>::iterator hbai;
117 RealType DAdist, DHdist, HAdist, theta, ctheta, Qk, q1, q2;
118 std::vector<std::pair<RealType, Molecule*>> myNeighbors;
119 int myIndex, ii, jj, index1, index2;
121 bool usePeriodicBoundaryConditions_ =
122 info_->getSimParams()->getUsePeriodicBoundaryConditions();
124 DumpReader reader(info_, dumpFilename_);
125 int nFrames = reader.getNFrames();
127 for (
int istep = 0; istep < nFrames; istep += step_) {
128 reader.readFrame(istep);
129 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
132 Q_.resize(info_->getNGlobalMolecules(), 0.0);
134 if (evaluator_.isDynamic()) {
135 seleMan_.setSelectionSet(evaluator_.evaluate());
140 for (mol1 = seleMan_.beginSelectedMolecule(ii); mol1 != NULL;
141 mol1 = seleMan_.nextSelectedMolecule(ii)) {
142 myIndex = mol1->getGlobalIndex();
150 for (mol2 = info_->beginMolecule(mi); mol2 != NULL;
151 mol2 = info_->nextMolecule(mi)) {
152 if (mol2->getGlobalIndex() != myIndex) {
153 vec = mol1->getCom() - mol2->getCom();
155 if (usePeriodicBoundaryConditions_)
156 currentSnapshot_->wrapVector(vec);
162 if (r < rCut_) { myNeighbors.push_back(std::make_pair(r, mol2)); }
167 std::sort(myNeighbors.begin(), myNeighbors.end());
171 int nbors = myNeighbors.size();
172 int nang = int(0.5 * (nbors * (nbors - 1)));
176 for (
int i = 0; i < nbors - 1; i++) {
177 moli = myNeighbors[i].second;
180 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(rik);
184 for (
int j = i + 1; j < nbors; j++) {
185 molj = myNeighbors[j].second;
188 if (usePeriodicBoundaryConditions_)
189 currentSnapshot_->wrapVector(rkj);
192 cospsi =
dot(rik, rkj);
196 Qk = Qk - (pow(cospsi + 1.0 / 3.0, 2) * 9.0 / (4.0 * nang));
200 if (nang > 0) { Q_[myIndex] = Qk; }
204 for (mol1 = seleMan_.beginSelectedMolecule(ii); mol1 != NULL;
205 mol1 = seleMan_.nextSelectedMolecule(ii)) {
206 for (mol2 = seleMan_.beginSelectedMolecule(jj); mol2 != NULL;
207 mol2 = seleMan_.nextSelectedMolecule(jj)) {
209 for (hbd = mol1->beginHBondDonor(hbdi); hbd != NULL;
210 hbd = mol1->nextHBondDonor(hbdi)) {
211 dPos = hbd->donorAtom->getPos();
212 hPos = hbd->donatedHydrogen->getPos();
214 currentSnapshot_->wrapVector(DH);
215 DHdist = DH.length();
218 for (hba = mol2->beginHBondAcceptor(hbai); hba != NULL;
219 hba = mol2->nextHBondAcceptor(hbai)) {
220 aPos = hba->getPos();
222 currentSnapshot_->wrapVector(DA);
223 DAdist = DA.length();
227 if (DAdist < OOCut_) {
229 currentSnapshot_->wrapVector(HA);
230 HAdist = HA.length();
232 ctheta =
dot(DH, DA) / (DHdist * DAdist);
233 theta = acos(ctheta) * 180.0 / Constants::PI;
236 if (theta < thetaCut_ && HAdist < OHCut_) {
238 index1 = mol1->getGlobalIndex();
239 index2 = mol2->getGlobalIndex();
242 collectHistogram(q1, q2);
248 for (hba = mol1->beginHBondAcceptor(hbai); hba != NULL;
249 hba = mol1->nextHBondAcceptor(hbai)) {
250 aPos = hba->getPos();
253 for (hbd = mol2->beginHBondDonor(hbdi); hbd != NULL;
254 hbd = mol2->nextHBondDonor(hbdi)) {
255 dPos = hbd->donorAtom->getPos();
258 currentSnapshot_->wrapVector(DA);
259 DAdist = DA.length();
263 if (DAdist < OOCut_) {
264 hPos = hbd->donatedHydrogen->getPos();
266 currentSnapshot_->wrapVector(HA);
267 HAdist = HA.length();
270 currentSnapshot_->wrapVector(DH);
271 DHdist = DH.length();
272 ctheta =
dot(DH, DA) / (DHdist * DAdist);
273 theta = acos(ctheta) * 180.0 / Constants::PI;
275 if (theta < thetaCut_ && HAdist < OHCut_) {
278 index1 = mol2->getGlobalIndex();
279 index2 = mol1->getGlobalIndex();
282 collectHistogram(q1, q2);
293 void TetrahedralityHBMatrix::collectHistogram(RealType q1, RealType q2) {
294 if (q1 > MinQ_ && q1 < MaxQ_) {
295 int bin1 = int((q1 - MinQ_) / deltaQ_);
296 if (q2 > MinQ_ && q2 < MaxQ_) {
297 int bin2 = int((q2 - MinQ_) / deltaQ_);
298 Q_histogram_[bin1][bin2] += 1;
308 void TetrahedralityHBMatrix::writeOutput() {
309 std::ofstream ofs(outputFilename_.c_str());
312 ofs <<
"# " << getAnalysisType() <<
"\n";
313 ofs <<
"# OpenMD " << r.getFullRevision() <<
"\n";
314 ofs <<
"# " << r.getBuildDate() <<
"\n";
315 ofs <<
"# selection script: \"" << selectionScript_ <<
"\"\n";
317 if (!paramString_.empty())
318 ofs <<
"# parameters: " << paramString_ <<
"\n";
320 ofs <<
"# Hydrogen Bond count: " << count_ <<
"\n";
322 for (
unsigned int i = 0; i < Q_histogram_.size(); ++i) {
323 for (
unsigned int j = 0; j < Q_histogram_[i].size(); ++j) {
324 ofs << RealType(Q_histogram_[i][j]) / RealType(count_) <<
"\t";
330 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
331 "TetrahedralityHBMatrix: unable to open %s\n",
332 outputFilename_.c_str());
333 painCave.isFatal = 1;
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)