OpenMD 3.1
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 evaluator1_.loadScriptString(sele1);
87 if (!evaluator1_.isDynamic()) {
88 seleMan1_.setSelectionSet(evaluator1_.evaluate());
89 }
90
91 evaluator2_.loadScriptString(sele2);
92 if (!evaluator2_.isDynamic()) {
93 seleMan2_.setSelectionSet(evaluator2_.evaluate());
94 }
95
96 setAnalysisType(
97 "2nd order Legendre Polynomial Correlation using r as reference axis");
98 setOutputName(getPrefix(filename) + ".P2R");
99 std::stringstream params;
100 const std::string paramString = params.str();
101 setParameterString(paramString);
102 }
103
104 P2R::P2R(SimInfo* info, const std::string& filename, const std::string& sele1,
105 int seleOffset, unsigned int nbins) :
106 StaticAnalyser(info, filename, nbins),
107 doVect_(false), doOffset_(true), doOffset2_(false),
108 selectionScript1_(sele1), seleMan1_(info), seleMan2_(info),
109 evaluator1_(info), evaluator2_(info), seleOffset_(seleOffset) {
110 evaluator1_.loadScriptString(sele1);
111 if (!evaluator1_.isDynamic()) {
112 seleMan1_.setSelectionSet(evaluator1_.evaluate());
113 }
114
115 setAnalysisType(
116 "2nd order Legendre Polynomial Correlation using r as reference axis");
117 setOutputName(getPrefix(filename) + ".P2R");
118 std::stringstream params;
119 const std::string paramString = params.str();
120 setParameterString(paramString);
121 }
122
123 P2R::P2R(SimInfo* info, const std::string& filename, const std::string& sele1,
124 int seleOffset, int seleOffset2, unsigned int nbins) :
125 StaticAnalyser(info, filename, nbins),
126 doVect_(false), doOffset_(true), doOffset2_(true),
127 selectionScript1_(sele1), seleMan1_(info), seleMan2_(info),
128 evaluator1_(info), evaluator2_(info), seleOffset_(seleOffset),
129 seleOffset2_(seleOffset2) {
130 evaluator1_.loadScriptString(sele1);
131 if (!evaluator1_.isDynamic()) {
132 seleMan1_.setSelectionSet(evaluator1_.evaluate());
133 }
134
135 setAnalysisType(
136 "2nd order Legendre Polynomial Correlation using r as reference axis");
137 setOutputName(getPrefix(filename) + ".P2R");
138 std::stringstream params;
139 const std::string paramString = params.str();
140 setParameterString(paramString);
141 }
142
143 void P2R::process() {
144 StuntDouble* sd1;
145 StuntDouble* sd2;
146 int ii;
147 int jj;
148 bool usePeriodicBoundaryConditions_ =
149 info_->getSimParams()->getUsePeriodicBoundaryConditions();
150
151 Thermo thermo(info_);
152 DumpReader reader(info_, dumpFilename_);
153 int nFrames = reader.getNFrames();
154
155 nProcessed_ = nFrames / step_;
156 P2_ = 0.0;
157 count_ = 0;
158
159 for (int istep = 0; istep < nFrames; istep += step_) {
160 reader.readFrame(istep);
161 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
162
163 Vector3d CenterOfMass = thermo.getCom();
164
165 if (evaluator1_.isDynamic()) {
166 seleMan1_.setSelectionSet(evaluator1_.evaluate());
167 }
168
169 if (doVect_) {
170 for (sd1 = seleMan1_.beginSelected(ii); sd1 != NULL;
171 sd1 = seleMan1_.nextSelected(ii)) {
172 Vector3d pos = sd1->getPos();
173
174 Vector3d r1 = CenterOfMass - pos;
175 // only do this if the stunt double actually has a vector associated
176 // with it
177 if (sd1->isDirectional()) {
178 Vector3d vec = sd1->getA().transpose() * V3Z;
179 vec.normalize();
180 r1.normalize();
181 RealType cosangle = dot(r1, vec);
182
183 P2_ += 0.5 * (3.0 * cosangle * cosangle - 1.0);
184 count_++;
185 }
186 }
187 } else {
188 if (doOffset_) {
189 for (sd1 = seleMan1_.beginSelected(ii); sd1 != NULL;
190 sd1 = seleMan1_.nextSelected(ii)) {
191 // This will require careful rewriting if StaticProps is
192 // ever parallelized. For an example, see
193 // Thermo::getTaggedAtomPairDistance
194 Vector3d r1;
195
196 if (doOffset2_) {
197 int sd1Aind = sd1->getGlobalIndex() + seleOffset2_;
198 StuntDouble* sd1A = info_->getIOIndexToIntegrableObject(sd1Aind);
199 r1 = CenterOfMass - sd1A->getPos();
200 } else {
201 r1 = CenterOfMass - sd1->getPos();
202 }
203
204 if (usePeriodicBoundaryConditions_)
205 currentSnapshot_->wrapVector(r1);
206
207 int sd2Index = sd1->getGlobalIndex() + seleOffset_;
208 sd2 = info_->getIOIndexToIntegrableObject(sd2Index);
209
210 Vector3d r2 = CenterOfMass - sd2->getPos();
211 if (usePeriodicBoundaryConditions_)
212 currentSnapshot_->wrapVector(r2);
213
214 Vector3d rc = 0.5 * (r1 + r2);
215 if (usePeriodicBoundaryConditions_)
216 currentSnapshot_->wrapVector(rc);
217
218 Vector3d vec = r1 - r2;
219 if (usePeriodicBoundaryConditions_)
220 currentSnapshot_->wrapVector(vec);
221
222 rc.normalize();
223 vec.normalize();
224 RealType cosangle = dot(rc, vec);
225 P2_ += 0.5 * (3.0 * cosangle * cosangle - 1.0);
226 count_++;
227 }
228 } else {
229 if (evaluator2_.isDynamic()) {
230 seleMan2_.setSelectionSet(evaluator2_.evaluate());
231 }
232
233 if (seleMan1_.getSelectionCount() != seleMan2_.getSelectionCount()) {
234 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
235 "In frame %d, the number of selected StuntDoubles are\n"
236 "\tnot the same in --sele1 and sele2\n",
237 istep);
238 painCave.severity = OPENMD_INFO;
239 painCave.isFatal = 0;
240 simError();
241 }
242
243 for (sd1 = seleMan1_.beginSelected(ii),
244 sd2 = seleMan2_.beginSelected(jj);
245 sd1 != NULL && sd2 != NULL; sd1 = seleMan1_.nextSelected(ii),
246 sd2 = seleMan2_.nextSelected(jj)) {
247 Vector3d r1 = CenterOfMass - sd1->getPos();
248 if (usePeriodicBoundaryConditions_)
249 currentSnapshot_->wrapVector(r1);
250
251 Vector3d r2 = CenterOfMass - sd2->getPos();
252 if (usePeriodicBoundaryConditions_)
253 currentSnapshot_->wrapVector(r2);
254
255 Vector3d rc = 0.5 * (r1 + r2);
256 if (usePeriodicBoundaryConditions_)
257 currentSnapshot_->wrapVector(rc);
258
259 Vector3d vec = r1 - r2;
260 if (usePeriodicBoundaryConditions_)
261 currentSnapshot_->wrapVector(vec);
262
263 rc.normalize();
264 vec.normalize();
265 RealType cosangle = dot(rc, vec);
266 P2_ += 0.5 * (3.0 * cosangle * cosangle - 1.0);
267 count_++;
268 }
269 }
270 }
271 }
272 processHistogram();
273 writeP2R();
274 }
275
276 void P2R::processHistogram() {
277 if (count_ > 0) P2_ /= count_;
278 }
279
280 void P2R::writeP2R() {
281 std::ofstream ofs(outputFilename_.c_str());
282 if (ofs.is_open()) {
283 Revision rev;
284
285 ofs << "# " << getAnalysisType() << "\n";
286 ofs << "# OpenMD " << rev.getFullRevision() << "\n";
287 ofs << "# " << rev.getBuildDate() << "\n";
288 ofs << "#nFrames:\t" << nProcessed_ << "\n";
289 ofs << "#selection1: (" << selectionScript1_ << ")";
290 if (!doVect_) { ofs << "\tselection2: (" << selectionScript2_ << ")"; }
291 ofs << "\n";
292 if (!paramString_.empty())
293 ofs << "# parameters: " << paramString_ << "\n";
294
295 ofs << "#P2 correlation:\n";
296 ofs << P2_ << "\n";
297
298 } else {
299 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
300 "P2R: unable to open %s\n", outputFilename_.c_str());
301 painCave.isFatal = 1;
302 simError();
303 }
304
305 ofs.close();
306 }
307
308 P2Z::P2Z(SimInfo* info, const std::string& filename, const std::string& sele1,
309 unsigned int nbins, int axis) :
310 P2R(info, filename, sele1, nbins),
311 axis_(axis) {
312 switch (axis_) {
313 case 0:
314 axisLabel_ = "x";
315 break;
316 case 1:
317 axisLabel_ = "y";
318 break;
319 case 2:
320 default:
321 axisLabel_ = "z";
322 break;
323 }
324
325 setAnalysisType("2nd order Legendre Polynomial Correlation using " +
326 axisLabel_ + " as reference axis");
327 setOutputName(getPrefix(filename) + ".P2Z");
328 std::stringstream params;
329 const std::string paramString = params.str();
330 setParameterString(paramString);
331 }
332
333 P2Z::P2Z(SimInfo* info, const std::string& filename, const std::string& sele1,
334 const std::string& sele2, unsigned int nbins, int axis) :
335 P2R(info, filename, sele1, sele2, nbins),
336 axis_(axis) {
337 switch (axis_) {
338 case 0:
339 axisLabel_ = "x";
340 break;
341 case 1:
342 axisLabel_ = "y";
343 break;
344 case 2:
345 default:
346 axisLabel_ = "z";
347 break;
348 }
349
350 setAnalysisType("2nd order Legendre Polynomial Correlation using " +
351 axisLabel_ + " as reference axis");
352 setOutputName(getPrefix(filename) + ".P2Z");
353 std::stringstream params;
354 const std::string paramString = params.str();
355 setParameterString(paramString);
356 }
357
358 P2Z::P2Z(SimInfo* info, const std::string& filename, const std::string& sele1,
359 int seleOffset, unsigned int nbins, int axis) :
360 P2R(info, filename, sele1, seleOffset, nbins),
361 axis_(axis) {
362 switch (axis_) {
363 case 0:
364 axisLabel_ = "x";
365 break;
366 case 1:
367 axisLabel_ = "y";
368 break;
369 case 2:
370 default:
371 axisLabel_ = "z";
372 break;
373 }
374
375 setAnalysisType("2nd order Legendre Polynomial Correlation using " +
376 axisLabel_ + " as reference axis");
377 setOutputName(getPrefix(filename) + ".P2Z");
378 std::stringstream params;
379 const std::string paramString = params.str();
380 setParameterString(paramString);
381 }
382
383 P2Z::P2Z(SimInfo* info, const std::string& filename, const std::string& sele1,
384 int seleOffset, int seleOffset2, unsigned int nbins, int axis) :
385 P2R(info, filename, sele1, seleOffset, seleOffset2, nbins),
386 axis_(axis) {
387 switch (axis_) {
388 case 0:
389 axisLabel_ = "x";
390 break;
391 case 1:
392 axisLabel_ = "y";
393 break;
394 case 2:
395 default:
396 axisLabel_ = "z";
397 break;
398 }
399
400 setAnalysisType("2nd order Legendre Polynomial Correlation using " +
401 axisLabel_ + " as reference axis");
402 setOutputName(getPrefix(filename) + ".P2Z");
403 std::stringstream params;
404 const std::string paramString = params.str();
405 setParameterString(paramString);
406 }
407
408 void P2Z::process() {
409 Vector3d zhat = V3Zero;
410 zhat[axis_] = 1.0; // unit vector along preferred axis
411
412 StuntDouble* sd1;
413 StuntDouble* sd2;
414 int ii;
415 int jj;
416 bool usePeriodicBoundaryConditions_ =
417 info_->getSimParams()->getUsePeriodicBoundaryConditions();
418
419 DumpReader reader(info_, dumpFilename_);
420 int nFrames = reader.getNFrames();
421
422 nProcessed_ = nFrames / step_;
423 P2_ = 0.0;
424 count_ = 0;
425
426 for (int istep = 0; istep < nFrames; istep += step_) {
427 reader.readFrame(istep);
428 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
429
430 if (evaluator1_.isDynamic()) {
431 seleMan1_.setSelectionSet(evaluator1_.evaluate());
432 }
433
434 if (doVect_) {
435 for (sd1 = seleMan1_.beginSelected(ii); sd1 != NULL;
436 sd1 = seleMan1_.nextSelected(ii)) {
437 // only do this if the stunt double actually has a vector associated
438 // with it
439 if (sd1->isDirectional()) {
440 Vector3d vec = sd1->getA().transpose() * V3Z;
441 vec.normalize();
442 RealType cosangle = dot(zhat, vec);
443
444 P2_ += 0.5 * (3.0 * cosangle * cosangle - 1.0);
445 count_++;
446 }
447 }
448 } else {
449 if (doOffset_) {
450 for (sd1 = seleMan1_.beginSelected(ii); sd1 != NULL;
451 sd1 = seleMan1_.nextSelected(ii)) {
452 // This will require careful rewriting if StaticProps is
453 // ever parallelized. For an example, see
454 // Thermo::getTaggedAtomPairDistance
455 Vector3d r1;
456
457 if (doOffset2_) {
458 int sd1Aind = sd1->getGlobalIndex() + seleOffset2_;
459 StuntDouble* sd1A = info_->getIOIndexToIntegrableObject(sd1Aind);
460 r1 = sd1A->getPos();
461 } else {
462 r1 = sd1->getPos();
463 }
464
465 int sd2Index = sd1->getGlobalIndex() + seleOffset_;
466 sd2 = info_->getIOIndexToIntegrableObject(sd2Index);
467
468 Vector3d r2 = sd2->getPos();
469 Vector3d vec = r1 - r2;
470
471 if (usePeriodicBoundaryConditions_)
472 currentSnapshot_->wrapVector(vec);
473
474 vec.normalize();
475 RealType cosangle = dot(zhat, vec);
476 P2_ += 0.5 * (3.0 * cosangle * cosangle - 1.0);
477 count_++;
478 }
479 } else {
480 if (evaluator2_.isDynamic()) {
481 seleMan2_.setSelectionSet(evaluator2_.evaluate());
482 }
483
484 if (seleMan1_.getSelectionCount() != seleMan2_.getSelectionCount()) {
485 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
486 "In frame %d, the number of selected StuntDoubles are\n"
487 "\tnot the same in --sele1 and sele2\n",
488 istep);
489 painCave.severity = OPENMD_INFO;
490 painCave.isFatal = 0;
491 simError();
492 }
493
494 for (sd1 = seleMan1_.beginSelected(ii),
495 sd2 = seleMan2_.beginSelected(jj);
496 sd1 != NULL && sd2 != NULL; sd1 = seleMan1_.nextSelected(ii),
497 sd2 = seleMan2_.nextSelected(jj)) {
498 Vector3d r1 = sd1->getPos();
499 Vector3d r2 = sd2->getPos();
500 Vector3d vec = r1 - r2;
501
502 if (usePeriodicBoundaryConditions_)
503 currentSnapshot_->wrapVector(vec);
504
505 vec.normalize();
506 RealType cosangle = dot(zhat, vec);
507 P2_ += 0.5 * (3.0 * cosangle * cosangle - 1.0);
508 count_++;
509 }
510 }
511 }
512 }
513 processHistogram();
514 writeP2R();
515 }
516
517} // 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)