OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
Displacement.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/dynamicProps/Displacement.hpp"
46
47#include <sstream>
48
49#include "utils/Revision.hpp"
50
51namespace OpenMD {
52 Displacement::Displacement(SimInfo* info, const std::string& filename,
53 const std::string& sele1,
54 const std::string& sele2) :
55 ObjectACF<Vector3d>(info, filename, sele1, sele2) {
56 setCorrFuncType("Displacement");
57 setOutputName(getPrefix(dumpFilename_) + ".disp");
58
59 positions_.resize(nFrames_);
60 }
61
62 DisplacementZ::DisplacementZ(SimInfo* info, const std::string& filename,
63 const std::string& sele1,
64 const std::string& sele2, int nZbins, int axis) :
65 ObjectACF<Vector3d>(info, filename, sele1, sele2) {
66 setCorrFuncType("Displacement binned by Z");
67 setOutputName(getPrefix(dumpFilename_) + ".dispZ");
68
69 positions_.resize(nFrames_);
70 zBins_.resize(nFrames_);
71 nZBins_ = nZbins;
72 axis_ = axis;
73
74 switch (axis_) {
75 case 0:
76 axisLabel_ = "x";
77 break;
78 case 1:
79 axisLabel_ = "y";
80 break;
81 case 2:
82 default:
83 axisLabel_ = "z";
84 break;
85 }
86
87 std::stringstream params;
88 params << " nzbins = " << nZBins_;
89 const std::string paramString = params.str();
90 setParameterString(paramString);
91
92 histograms_.resize(nTimeBins_);
93 counts_.resize(nTimeBins_);
94 for (unsigned int i = 0; i < nTimeBins_; i++) {
95 histograms_[i].resize(nZBins_);
96 counts_[i].resize(nZBins_);
97 std::fill(histograms_[i].begin(), histograms_[i].end(), Vector3d(0.0));
98 std::fill(counts_[i].begin(), counts_[i].end(), 0);
99 }
100 }
101
102 int Displacement::computeProperty1(int frame, StuntDouble* sd) {
103 positions_[frame].push_back(sd->getPos());
104 return positions_[frame].size() - 1;
105 }
106
107 Vector3d Displacement::calcCorrVal(int frame1, int frame2, int id1, int id2) {
108 return positions_[frame2][id2] - positions_[frame1][id1];
109 }
110
111 void DisplacementZ::computeFrame(int istep) {
112 hmat_ = currentSnapshot_->getHmat();
113 halfBoxZ_ = hmat_(axis_, axis_) / 2.0;
114
115 StuntDouble* sd;
116
117 int isd1, isd2;
118 unsigned int index;
119
120 if (evaluator1_.isDynamic()) {
121 seleMan1_.setSelectionSet(evaluator1_.evaluate());
122 }
123
124 if (uniqueSelections_ && evaluator2_.isDynamic()) {
125 seleMan2_.setSelectionSet(evaluator2_.evaluate());
126 }
127
128 for (sd = seleMan1_.beginSelected(isd1); sd != NULL;
129 sd = seleMan1_.nextSelected(isd1)) {
130 index = computeProperty1(istep, sd);
131 if (index == sele1ToIndex_[istep].size()) {
132 sele1ToIndex_[istep].push_back(sd->getGlobalIndex());
133 } else {
134 sele1ToIndex_[istep].resize(index + 1);
135 sele1ToIndex_[istep][index] = sd->getGlobalIndex();
136 }
137 }
138
139 if (uniqueSelections_) {
140 for (sd = seleMan2_.beginSelected(isd2); sd != NULL;
141 sd = seleMan2_.nextSelected(isd2)) {
142 index = computeProperty1(istep, sd);
143
144 if (index == sele2ToIndex_[istep].size()) {
145 sele2ToIndex_[istep].push_back(sd->getGlobalIndex());
146 } else {
147 sele2ToIndex_[istep].resize(index + 1);
148 sele2ToIndex_[istep][index] = sd->getGlobalIndex();
149 }
150 }
151 }
152 }
153
154 int DisplacementZ::computeProperty1(int frame, StuntDouble* sd) {
155 Vector3d pos = sd->getPos();
156 // we need the raw (not wrapped) positions for RMSD:
157 positions_[frame].push_back(sd->getPos());
158
159 if (info_->getSimParams()->getUsePeriodicBoundaryConditions()) {
160 currentSnapshot_->wrapVector(pos);
161 }
162 int zBin = int(nZBins_ * (halfBoxZ_ + pos[axis_]) / hmat_(axis_, axis_));
163 zBins_[frame].push_back(zBin);
164
165 return positions_[frame].size() - 1;
166 }
167
168 void DisplacementZ::correlateFrames(int frame1, int frame2, int timeBin) {
169 std::vector<int> s1;
170 std::vector<int> s2;
171
172 std::vector<int>::iterator i1;
173 std::vector<int>::iterator i2;
174
175 s1 = sele1ToIndex_[frame1];
176
177 if (uniqueSelections_)
178 s2 = sele2ToIndex_[frame2];
179 else
180 s2 = sele1ToIndex_[frame2];
181
182 for (i1 = s1.begin(), i2 = s2.begin(); i1 != s1.end() && i2 != s2.end();
183 ++i1, ++i2) {
184 // If the selections are dynamic, they might not have the
185 // same objects in both frames, so we need to roll either of
186 // the selections until we have the same object to
187 // correlate.
188
189 while (i1 != s1.end() && *i1 < *i2) {
190 ++i1;
191 }
192
193 while (i2 != s2.end() && *i2 < *i1) {
194 ++i2;
195 }
196
197 if (i1 == s1.end() || i2 == s2.end()) break;
198
199 calcCorrValImpl(frame1, frame2, i1 - s1.begin(), i2 - s2.begin(),
200 timeBin);
201 }
202 }
203
204 Vector3d DisplacementZ::calcCorrValImpl(int frame1, int frame2, int id1,
205 int id2, int timeBin) {
206 int zBin1 = zBins_[frame1][id1];
207 int zBin2 = zBins_[frame2][id2];
208
209 if (zBin1 == zBin2) {
210 Vector3d diff = positions_[frame2][id2] - positions_[frame1][id1];
211 histograms_[timeBin][zBin1] += diff;
212 counts_[timeBin][zBin1]++;
213 }
214 return Vector3d(0.0);
215 }
216
217 void DisplacementZ::postCorrelate() {
218 for (unsigned int i = 0; i < nTimeBins_; ++i) {
219 for (unsigned int j = 0; j < nZBins_; ++j) {
220 if (counts_[i][j] > 0) {
221 histograms_[i][j] /= counts_[i][j];
222 } else {
223 histograms_[i][j] = Vector3d(0.0);
224 }
225 }
226 }
227 }
228 void DisplacementZ::writeCorrelate() {
229 std::ofstream ofs(getOutputFileName().c_str());
230
231 if (ofs.is_open()) {
232 Revision r;
233
234 ofs << "# " << getCorrFuncType() << "\n";
235 ofs << "# OpenMD " << r.getFullRevision() << "\n";
236 ofs << "# " << r.getBuildDate() << "\n";
237 ofs << "# selection script1: \"" << selectionScript1_;
238 ofs << "\"\tselection script2: \"" << selectionScript2_ << "\"\n";
239 ofs << "# privilegedAxis computed as " << axisLabel_ << " axis \n";
240 if (!paramString_.empty())
241 ofs << "# parameters: " << paramString_ << "\n";
242
243 ofs << "#time\tcorrVal\n";
244
245 for (unsigned int i = 0; i < nTimeBins_; ++i) {
246 ofs << times_[i] - times_[0] << "\t";
247
248 for (unsigned int j = 0; j < nZBins_; ++j) {
249 for (int k = 0; k < 3; k++) {
250 ofs << histograms_[i][j](k) << '\t';
251 }
252 }
253
254 ofs << "\n";
255 }
256
257 } else {
258 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
259 "DisplacementZ::writeCorrelate Error: fail to open %s\n",
260 getOutputFileName().c_str());
261 painCave.isFatal = 1;
262 simError();
263 }
264 ofs.close();
265 }
266} // namespace OpenMD
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)