OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
P2R.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/* Calculates Angle(R) for DirectionalAtoms*/
46
47#include "applications/staticProps/P2R.hpp"
48
49#include <algorithm>
50#include <cmath>
51#include <fstream>
52#include <sstream>
53
54#include "brains/Thermo.hpp"
55#include "io/DumpReader.hpp"
57#include "utils/Revision.hpp"
58#include "utils/simError.h"
59
60namespace OpenMD {
61
62 P2R::P2R(SimInfo* info, const std::string& filename, const std::string& sele1,
63 unsigned int nbins) :
64 StaticAnalyser(info, filename, nbins),
65 doVect_(true), doOffset_(false), selectionScript1_(sele1),
66 seleMan1_(info), seleMan2_(info), evaluator1_(info), evaluator2_(info) {
67 evaluator1_.loadScriptString(sele1);
68 if (!evaluator1_.isDynamic()) {
69 seleMan1_.setSelectionSet(evaluator1_.evaluate());
70 }
71
72 setAnalysisType(
73 "2nd order Legendre Polynomial Correlation using r as reference axis");
74 setOutputName(getPrefix(filename) + ".P2R");
75 std::stringstream params;
76 const std::string paramString = params.str();
77 setParameterString(paramString);
78 }
79
80 P2R::P2R(SimInfo* info, const std::string& filename, const std::string& sele1,
81 const std::string& sele2, unsigned int nbins) :
82 StaticAnalyser(info, filename, nbins),
83 doVect_(false), doOffset_(false), selectionScript1_(sele1),
84 selectionScript2_(sele2), seleMan1_(info), seleMan2_(info),
85 evaluator1_(info), evaluator2_(info) {
86 setOutputName(getPrefix(filename) + ".P2R");
87
88 evaluator1_.loadScriptString(sele1);
89 if (!evaluator1_.isDynamic()) {
90 seleMan1_.setSelectionSet(evaluator1_.evaluate());
91 }
92
93 evaluator2_.loadScriptString(sele2);
94 if (!evaluator2_.isDynamic()) {
95 seleMan2_.setSelectionSet(evaluator2_.evaluate());
96 }
97
98 setAnalysisType(
99 "2nd order Legendre Polynomial Correlation using r as reference axis");
100 setOutputName(getPrefix(filename) + ".P2R");
101 std::stringstream params;
102 const std::string paramString = params.str();
103 setParameterString(paramString);
104 }
105
106 P2R::P2R(SimInfo* info, const std::string& filename, const std::string& sele1,
107 int seleOffset, unsigned int nbins) :
108 StaticAnalyser(info, filename, nbins),
109 doVect_(false), doOffset_(true), doOffset2_(false),
110 selectionScript1_(sele1), seleMan1_(info), seleMan2_(info),
111 evaluator1_(info), evaluator2_(info), seleOffset_(seleOffset) {
112 setOutputName(getPrefix(filename) + ".P2R");
113
114 evaluator1_.loadScriptString(sele1);
115 if (!evaluator1_.isDynamic()) {
116 seleMan1_.setSelectionSet(evaluator1_.evaluate());
117 }
118
119 setAnalysisType(
120 "2nd order Legendre Polynomial Correlation using r as reference axis");
121 setOutputName(getPrefix(filename) + ".P2R");
122 std::stringstream params;
123 const std::string paramString = params.str();
124 setParameterString(paramString);
125 }
126
127 P2R::P2R(SimInfo* info, const std::string& filename, const std::string& sele1,
128 int seleOffset, int seleOffset2, unsigned int nbins) :
129 StaticAnalyser(info, filename, nbins),
130 doVect_(false), doOffset_(true), doOffset2_(true),
131 selectionScript1_(sele1), seleMan1_(info), seleMan2_(info),
132 evaluator1_(info), evaluator2_(info), seleOffset_(seleOffset),
133 seleOffset2_(seleOffset2) {
134 setOutputName(getPrefix(filename) + ".P2R");
135
136 evaluator1_.loadScriptString(sele1);
137 if (!evaluator1_.isDynamic()) {
138 seleMan1_.setSelectionSet(evaluator1_.evaluate());
139 }
140
141 setAnalysisType(
142 "2nd order Legendre Polynomial Correlation using r as reference axis");
143 setOutputName(getPrefix(filename) + ".P2R");
144 std::stringstream params;
145 const std::string paramString = params.str();
146 setParameterString(paramString);
147 }
148
149 void P2R::process() {
150 StuntDouble* sd1;
151 StuntDouble* sd2;
152 int ii;
153 int jj;
154 bool usePeriodicBoundaryConditions_ =
155 info_->getSimParams()->getUsePeriodicBoundaryConditions();
156
157 Thermo thermo(info_);
158 DumpReader reader(info_, dumpFilename_);
159 int nFrames = reader.getNFrames();
160
161 nProcessed_ = nFrames / step_;
162
163 for (int istep = 0; istep < nFrames; istep += step_) {
164 reader.readFrame(istep);
165 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
166
167 Vector3d CenterOfMass = thermo.getCom();
168
169 if (evaluator1_.isDynamic()) {
170 seleMan1_.setSelectionSet(evaluator1_.evaluate());
171 }
172
173 if (doVect_) {
174 for (sd1 = seleMan1_.beginSelected(ii); sd1 != NULL;
175 sd1 = seleMan1_.nextSelected(ii)) {
176 Vector3d pos = sd1->getPos();
177
178 Vector3d r1 = CenterOfMass - pos;
179 // only do this if the stunt double actually has a vector associated
180 // with it
181 if (sd1->isDirectional()) {
182 Vector3d vec = sd1->getA().transpose() * V3Z;
183 vec.normalize();
184 r1.normalize();
185 RealType cosangle = dot(r1, vec);
186
187 P2_ += 0.5 * (3.0 * cosangle * cosangle - 1.0);
188 count_++;
189 }
190 }
191 } else {
192 if (doOffset_) {
193 for (sd1 = seleMan1_.beginSelected(ii); sd1 != NULL;
194 sd1 = seleMan1_.nextSelected(ii)) {
195 // This will require careful rewriting if StaticProps is
196 // ever parallelized. For an example, see
197 // Thermo::getTaggedAtomPairDistance
198 Vector3d r1;
199
200 if (doOffset2_) {
201 int sd1Aind = sd1->getGlobalIndex() + seleOffset2_;
202 StuntDouble* sd1A = info_->getIOIndexToIntegrableObject(sd1Aind);
203 r1 = CenterOfMass - sd1A->getPos();
204 } else {
205 r1 = CenterOfMass - sd1->getPos();
206 }
207
208 if (usePeriodicBoundaryConditions_)
209 currentSnapshot_->wrapVector(r1);
210
211 int sd2Index = sd1->getGlobalIndex() + seleOffset_;
212 sd2 = info_->getIOIndexToIntegrableObject(sd2Index);
213
214 Vector3d r2 = CenterOfMass - sd2->getPos();
215 if (usePeriodicBoundaryConditions_)
216 currentSnapshot_->wrapVector(r1);
217
218 Vector3d rc = 0.5 * (r1 + r2);
219 if (usePeriodicBoundaryConditions_)
220 currentSnapshot_->wrapVector(rc);
221
222 Vector3d vec = r1 - r2;
223 if (usePeriodicBoundaryConditions_)
224 currentSnapshot_->wrapVector(vec);
225
226 rc.normalize();
227 vec.normalize();
228 RealType cosangle = dot(rc, vec);
229 P2_ += 0.5 * (3.0 * cosangle * cosangle - 1.0);
230 count_++;
231 }
232 } else {
233 if (evaluator2_.isDynamic()) {
234 seleMan2_.setSelectionSet(evaluator2_.evaluate());
235 }
236
237 if (seleMan1_.getSelectionCount() != seleMan2_.getSelectionCount()) {
238 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
239 "In frame %d, the number of selected StuntDoubles are\n"
240 "\tnot the same in --sele1 and sele2\n",
241 istep);
242 painCave.severity = OPENMD_INFO;
243 painCave.isFatal = 0;
244 simError();
245 }
246
247 for (sd1 = seleMan1_.beginSelected(ii),
248 sd2 = seleMan2_.beginSelected(jj);
249 sd1 != NULL && sd2 != NULL; sd1 = seleMan1_.nextSelected(ii),
250 sd2 = seleMan2_.nextSelected(jj)) {
251 Vector3d r1 = CenterOfMass - sd1->getPos();
252 if (usePeriodicBoundaryConditions_)
253 currentSnapshot_->wrapVector(r1);
254
255 Vector3d r2 = CenterOfMass - sd2->getPos();
256 if (usePeriodicBoundaryConditions_)
257 currentSnapshot_->wrapVector(r1);
258
259 Vector3d rc = 0.5 * (r1 + r2);
260 if (usePeriodicBoundaryConditions_)
261 currentSnapshot_->wrapVector(rc);
262
263 Vector3d vec = r1 - r2;
264 if (usePeriodicBoundaryConditions_)
265 currentSnapshot_->wrapVector(vec);
266
267 rc.normalize();
268 vec.normalize();
269 RealType cosangle = dot(rc, vec);
270 P2_ += 0.5 * (3.0 * cosangle * cosangle - 1.0);
271 count_++;
272 }
273 }
274 }
275 }
276 processHistogram();
277 writeP2R();
278 }
279
280 void P2R::processHistogram() {
281 if (count_ > 0) P2_ /= count_;
282 }
283
284 void P2R::writeP2R() {
285 std::ofstream ofs(outputFilename_.c_str());
286 if (ofs.is_open()) {
287 Revision rev;
288
289 ofs << "# " << getAnalysisType() << "\n";
290 ofs << "# OpenMD " << rev.getFullRevision() << "\n";
291 ofs << "# " << rev.getBuildDate() << "\n";
292 ofs << "#nFrames:\t" << nProcessed_ << "\n";
293 ofs << "#selection1: (" << selectionScript1_ << ")";
294 if (!doVect_) { ofs << "\tselection2: (" << selectionScript2_ << ")"; }
295 ofs << "\n";
296 if (!paramString_.empty())
297 ofs << "# parameters: " << paramString_ << "\n";
298
299 ofs << "#P2 correlation:\n";
300 ofs << P2_ << "\n";
301
302 } else {
303 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
304 "P2R: unable to open %s\n", outputFilename_.c_str());
305 painCave.isFatal = 1;
306 simError();
307 }
308
309 ofs.close();
310 }
311
312} // namespace OpenMD
void normalize()
Normalizes this vector in place.
Definition Vector.hpp:402
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)