48#include "applications/staticProps/TetrahedralityHBMatrix.hpp"
54#include "utils/Constants.hpp"
55#include "utils/Revision.hpp"
56#include "utils/simError.h"
60 TetrahedralityHBMatrix::TetrahedralityHBMatrix(
61 SimInfo* info,
const std::string& filename,
const std::string& sele,
62 double rCut,
double OOcut,
double thetaCut,
double OHcut,
int nbins) :
64 selectionScript_(sele), seleMan_(info), evaluator_(info), rCut_(rCut),
65 OOCut_(OOcut), thetaCut_(thetaCut), OHCut_(OHcut) {
66 setAnalysisType(
"Tetrahedrality HBond Matrix");
67 setOutputName(
getPrefix(filename) +
".hbq");
69 evaluator_.loadScriptString(sele);
70 if (!evaluator_.isDynamic()) {
71 seleMan_.setSelectionSet(evaluator_.evaluate());
74 Q_histogram_.resize(nBins_);
76 for (
unsigned int i = 0; i < nBins_; i++) {
77 Q_histogram_[i].resize(nBins_);
84 deltaQ_ = (MaxQ_ - MinQ_) / nBins_;
86 std::stringstream params;
87 params <<
" rCut = " << rCut_ <<
", OOcut = " << OOCut_
88 <<
", thetacut = " << thetaCut_ <<
", OHcut = " << OHCut_
89 <<
", nbins = " << nBins_ <<
", deltaQ = " << deltaQ_;
90 const std::string paramString = params.str();
91 setParameterString(paramString);
94 void TetrahedralityHBMatrix::initializeHistogram() {
95 for (
unsigned int i = 0; i < nBins_; i++) {
96 std::fill(Q_histogram_[i].begin(), Q_histogram_[i].end(), 0);
100 void TetrahedralityHBMatrix::process() {
105 SimInfo::MoleculeIterator mi;
107 Vector3d ri, rj, rk, rik, rkj, dposition, tposition;
109 std::vector<Molecule::HBondDonor*>::iterator hbdi;
110 Molecule::HBondDonor* hbd;
111 std::vector<Atom*>::iterator hbai;
120 RealType DAdist, DHdist, HAdist, theta, ctheta, Qk, q1, q2;
121 std::vector<std::pair<RealType, Molecule*>> myNeighbors;
122 int myIndex, ii, jj, index1, index2;
124 bool usePeriodicBoundaryConditions_ =
125 info_->getSimParams()->getUsePeriodicBoundaryConditions();
127 DumpReader reader(info_, dumpFilename_);
128 int nFrames = reader.getNFrames();
130 for (
int istep = 0; istep < nFrames; istep += step_) {
131 reader.readFrame(istep);
132 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
135 Q_.resize(info_->getNGlobalMolecules(), 0.0);
137 if (evaluator_.isDynamic()) {
138 seleMan_.setSelectionSet(evaluator_.evaluate());
143 for (mol1 = seleMan_.beginSelectedMolecule(ii); mol1 != NULL;
144 mol1 = seleMan_.nextSelectedMolecule(ii)) {
145 myIndex = mol1->getGlobalIndex();
153 for (mol2 = info_->beginMolecule(mi); mol2 != NULL;
154 mol2 = info_->nextMolecule(mi)) {
155 if (mol2->getGlobalIndex() != myIndex) {
156 vec = mol1->getCom() - mol2->getCom();
158 if (usePeriodicBoundaryConditions_)
159 currentSnapshot_->wrapVector(vec);
165 if (r < rCut_) { myNeighbors.push_back(std::make_pair(r, mol2)); }
170 std::sort(myNeighbors.begin(), myNeighbors.end());
174 int nbors = myNeighbors.size();
175 int nang = int(0.5 * (nbors * (nbors - 1)));
179 for (
int i = 0; i < nbors - 1; i++) {
180 moli = myNeighbors[i].second;
183 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(rik);
187 for (
int j = i + 1; j < nbors; j++) {
188 molj = myNeighbors[j].second;
191 if (usePeriodicBoundaryConditions_)
192 currentSnapshot_->wrapVector(rkj);
195 cospsi =
dot(rik, rkj);
199 Qk = Qk - (pow(cospsi + 1.0 / 3.0, 2) * 9.0 / (4.0 * nang));
203 if (nang > 0) { Q_[myIndex] = Qk; }
207 for (mol1 = seleMan_.beginSelectedMolecule(ii); mol1 != NULL;
208 mol1 = seleMan_.nextSelectedMolecule(ii)) {
209 for (mol2 = seleMan_.beginSelectedMolecule(jj); mol2 != NULL;
210 mol2 = seleMan_.nextSelectedMolecule(jj)) {
212 for (hbd = mol1->beginHBondDonor(hbdi); hbd != NULL;
213 hbd = mol1->nextHBondDonor(hbdi)) {
214 dPos = hbd->donorAtom->getPos();
215 hPos = hbd->donatedHydrogen->getPos();
217 currentSnapshot_->wrapVector(DH);
218 DHdist = DH.length();
221 for (hba = mol2->beginHBondAcceptor(hbai); hba != NULL;
222 hba = mol2->nextHBondAcceptor(hbai)) {
223 aPos = hba->getPos();
225 currentSnapshot_->wrapVector(DA);
226 DAdist = DA.length();
230 if (DAdist < OOCut_) {
232 currentSnapshot_->wrapVector(HA);
233 HAdist = HA.length();
235 ctheta =
dot(DH, DA) / (DHdist * DAdist);
236 theta = acos(ctheta) * 180.0 / Constants::PI;
239 if (theta < thetaCut_ && HAdist < OHCut_) {
241 index1 = mol1->getGlobalIndex();
242 index2 = mol2->getGlobalIndex();
245 collectHistogram(q1, q2);
251 for (hba = mol1->beginHBondAcceptor(hbai); hba != NULL;
252 hba = mol1->nextHBondAcceptor(hbai)) {
253 aPos = hba->getPos();
256 for (hbd = mol2->beginHBondDonor(hbdi); hbd != NULL;
257 hbd = mol2->nextHBondDonor(hbdi)) {
258 dPos = hbd->donorAtom->getPos();
261 currentSnapshot_->wrapVector(DA);
262 DAdist = DA.length();
266 if (DAdist < OOCut_) {
267 hPos = hbd->donatedHydrogen->getPos();
269 currentSnapshot_->wrapVector(HA);
270 HAdist = HA.length();
273 currentSnapshot_->wrapVector(DH);
274 DHdist = DH.length();
275 ctheta =
dot(DH, DA) / (DHdist * DAdist);
276 theta = acos(ctheta) * 180.0 / Constants::PI;
278 if (theta < thetaCut_ && HAdist < OHCut_) {
281 index1 = mol2->getGlobalIndex();
282 index2 = mol1->getGlobalIndex();
285 collectHistogram(q1, q2);
296 void TetrahedralityHBMatrix::collectHistogram(RealType q1, RealType q2) {
297 if (q1 > MinQ_ && q1 < MaxQ_) {
298 int bin1 = int((q1 - MinQ_) / deltaQ_);
299 if (q2 > MinQ_ && q2 < MaxQ_) {
300 int bin2 = int((q2 - MinQ_) / deltaQ_);
301 Q_histogram_[bin1][bin2] += 1;
311 void TetrahedralityHBMatrix::writeOutput() {
312 std::ofstream ofs(outputFilename_.c_str());
315 ofs <<
"# " << getAnalysisType() <<
"\n";
316 ofs <<
"# OpenMD " << r.getFullRevision() <<
"\n";
317 ofs <<
"# " << r.getBuildDate() <<
"\n";
318 ofs <<
"# selection script: \"" << selectionScript_ <<
"\"\n";
320 if (!paramString_.empty())
321 ofs <<
"# parameters: " << paramString_ <<
"\n";
323 ofs <<
"# Hydrogen Bond count: " << count_ <<
"\n";
325 for (
unsigned int i = 0; i < Q_histogram_.size(); ++i) {
326 for (
unsigned int j = 0; j < Q_histogram_[i].size(); ++j) {
327 ofs << RealType(Q_histogram_[i][j]) / RealType(count_) <<
"\t";
333 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
334 "TetrahedralityHBMatrix: unable to open %s\n",
335 outputFilename_.c_str());
336 painCave.isFatal = 1;
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
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)