OpenMD 3.1
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
TetrahedralityParamR.cpp
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45#include "applications/staticProps/TetrahedralityParamR.hpp"
46
47#include <algorithm>
48#include <fstream>
49#include <vector>
50
51#include "io/DumpReader.hpp"
53#include "utils/Revision.hpp"
54#include "utils/simError.h"
55
56#define HONKING_LARGE_VALUE 1.0e10
57
58using namespace std;
59namespace OpenMD {
60 TetrahedralityParamR::TetrahedralityParamR(
61 SimInfo* info, const std::string& filename, const std::string& sele1,
62 const std::string& sele2, const std::string& sele3, RealType rCut,
63 RealType len, int nrbins) :
64 StaticAnalyser(info, filename, nrbins),
65 selectionScript1_(sele1), selectionScript2_(sele2),
66 selectionScript3_(sele3), seleMan1_(info), seleMan2_(info),
67 seleMan3_(info), evaluator1_(info), evaluator2_(info), evaluator3_(info),
68 len_(len), nBins_(nrbins) {
69 setAnalysisType("Tetrahedrality Parameter(r)");
70
71 evaluator1_.loadScriptString(sele1);
72 if (!evaluator1_.isDynamic()) {
73 seleMan1_.setSelectionSet(evaluator1_.evaluate());
74 }
75
76 evaluator2_.loadScriptString(sele2);
77 if (!evaluator2_.isDynamic()) {
78 seleMan2_.setSelectionSet(evaluator2_.evaluate());
79 }
80
81 evaluator3_.loadScriptString(sele3);
82 if (!evaluator3_.isDynamic()) {
83 seleMan3_.setSelectionSet(evaluator3_.evaluate());
84 }
85
86 // Set up cutoff radius:
87 rCut_ = rCut;
88
89 deltaR_ = len_ / nBins_;
90
91 // fixed number of bins
92 sliceQ_.resize(nBins_);
93 sliceCount_.resize(nBins_);
94 std::fill(sliceQ_.begin(), sliceQ_.end(), 0.0);
95 std::fill(sliceCount_.begin(), sliceCount_.end(), 0);
96
97 setOutputName(getPrefix(filename) + ".Qr");
98 }
99
100 void TetrahedralityParamR::process() {
101 StuntDouble* sd;
102 StuntDouble* sd2;
103 StuntDouble* sd3;
104 StuntDouble* sdi;
105 StuntDouble* sdj;
106 int myIndex;
107 Vector3d vec;
108 Vector3d ri, rj, rk, rik, rkj;
109 RealType r;
110 RealType cospsi;
111 RealType Qk;
112 std::vector<std::pair<RealType, StuntDouble*>> myNeighbors;
113 int isd1;
114 int isd2;
115 int isd3;
116 bool usePeriodicBoundaryConditions_ =
117 info_->getSimParams()->getUsePeriodicBoundaryConditions();
118
119 DumpReader reader(info_, dumpFilename_);
120 int nFrames = reader.getNFrames();
121
122 for (int istep = 0; istep < nFrames; istep += step_) {
123 reader.readFrame(istep);
124 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
125
126 if (evaluator1_.isDynamic()) {
127 seleMan1_.setSelectionSet(evaluator1_.evaluate());
128 }
129
130 if (evaluator2_.isDynamic()) {
131 seleMan2_.setSelectionSet(evaluator2_.evaluate());
132 }
133
134 if (evaluator3_.isDynamic()) {
135 seleMan3_.setSelectionSet(evaluator3_.evaluate());
136 }
137
138 // outer loop is over the selected StuntDoubles:
139 for (sd = seleMan1_.beginSelected(isd1); sd != NULL;
140 sd = seleMan1_.nextSelected(isd1)) {
141 myIndex = sd->getGlobalIndex();
142
143 Qk = 1.0;
144 myNeighbors.clear();
145
146 for (sd2 = seleMan2_.beginSelected(isd2); sd2 != NULL;
147 sd2 = seleMan2_.nextSelected(isd2)) {
148 if (sd2->getGlobalIndex() != myIndex) {
149 vec = sd->getPos() - sd2->getPos();
150
151 if (usePeriodicBoundaryConditions_)
152 currentSnapshot_->wrapVector(vec);
153
154 r = vec.length();
155
156 // Check to see if neighbor is in bond cutoff
157
158 if (r < rCut_) { myNeighbors.push_back(std::make_pair(r, sd2)); }
159 }
160 }
161
162 // Sort the vector using predicate and std::sort
163 std::sort(myNeighbors.begin(), myNeighbors.end());
164
165 // Use only the 4 closest neighbors to do the rest of the work:
166
167 int nbors = myNeighbors.size() > 4 ? 4 : myNeighbors.size();
168 int nang = int(0.5 * (nbors * (nbors - 1)));
169
170 rk = sd->getPos();
171
172 for (int i = 0; i < nbors - 1; i++) {
173 sdi = myNeighbors[i].second;
174 ri = sdi->getPos();
175 rik = rk - ri;
176 if (usePeriodicBoundaryConditions_) currentSnapshot_->wrapVector(rik);
177
178 rik.normalize();
179
180 for (int j = i + 1; j < nbors; j++) {
181 sdj = myNeighbors[j].second;
182 rj = sdj->getPos();
183 rkj = rk - rj;
184 if (usePeriodicBoundaryConditions_)
185 currentSnapshot_->wrapVector(rkj);
186 rkj.normalize();
187
188 cospsi = dot(rik, rkj);
189
190 // Calculates scaled Qk for each molecule using calculated
191 // angles from 4 or fewer nearest neighbors.
192 Qk -= (pow(cospsi + 1.0 / 3.0, 2) * 2.25 / nang);
193 }
194 }
195
196 if (nang > 0) {
197 RealType shortest = HONKING_LARGE_VALUE;
198
199 // loop over selection 3 to find closest atom in selection 3:
200 for (sd3 = seleMan3_.beginSelected(isd3); sd3 != NULL;
201 sd3 = seleMan3_.nextSelected(isd3)) {
202 vec = sd->getPos() - sd3->getPos();
203
204 if (usePeriodicBoundaryConditions_)
205 currentSnapshot_->wrapVector(vec);
206
207 r = vec.length();
208
209 if (r < shortest) shortest = r;
210 }
211
212 int whichBin = int(shortest / deltaR_);
213 if (whichBin < int(nBins_)) {
214 sliceQ_[whichBin] += Qk;
215 sliceCount_[whichBin] += 1;
216 }
217 }
218 }
219 }
220 writeQr();
221 }
222
223 void TetrahedralityParamR::writeQr() {
224 Revision rev;
225 std::ofstream qRstream(outputFilename_.c_str());
226 if (qRstream.is_open()) {
227 qRstream << "# " << getAnalysisType() << "\n";
228 qRstream << "# OpenMD " << rev.getFullRevision() << "\n";
229 qRstream << "# " << rev.getBuildDate() << "\n";
230 qRstream << "#selection 1: (" << selectionScript1_ << ")\n";
231 qRstream << "#selection 2: (" << selectionScript2_ << ")\n";
232 qRstream << "#selection 3: (" << selectionScript3_ << ")\n";
233 if (!paramString_.empty())
234 qRstream << "# parameters: " << paramString_ << "\n";
235
236 qRstream << "#distance"
237 << "\tQk\n";
238 for (unsigned int i = 0; i < sliceQ_.size(); ++i) {
239 RealType Rval = (i + 0.5) * deltaR_;
240 if (sliceCount_[i] != 0) {
241 qRstream << Rval << "\t" << sliceQ_[i] / (RealType)sliceCount_[i]
242 << "\n";
243 }
244 }
245
246 } else {
247 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
248 "TetrahedralityParamR: unable to open %s\n",
249 outputFilename_.c_str());
250 painCave.isFatal = 1;
251 simError();
252 }
253 qRstream.close();
254 }
255} // namespace OpenMD
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)