OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
SCDOrderParameter.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/SCDOrderParameter.hpp"
46
47#include <string>
48#include <tuple>
49#include <vector>
50
51#include "io/DumpReader.hpp"
53#include "utils/simError.h"
54
55namespace OpenMD {
56
57 SCDElem::SCDElem(SimInfo* info, const std::string& sele1,
58 const std::string& sele2, const std::string& sele3) :
59 sele1_(sele1),
60 sele2_(sele2), sele3_(sele3) {
61 usePeriodicBoundaryConditions_ =
62 info->getSimParams()->getUsePeriodicBoundaryConditions();
63
64 SelectionManager seleMan1_(info);
65 SelectionManager seleMan2_(info);
66 SelectionManager seleMan3_(info);
67 SelectionEvaluator evaluator1_(info);
68 SelectionEvaluator evaluator2_(info);
69 SelectionEvaluator evaluator3_(info);
70
71 evaluator1_.loadScriptString(sele1_);
72 evaluator2_.loadScriptString(sele2_);
73 evaluator3_.loadScriptString(sele3_);
74
75 if (!evaluator1_.isDynamic()) {
76 seleMan1_.setSelectionSet(evaluator1_.evaluate());
77 } else {
78 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
79 "dynamic selection is not allowed\n");
80 painCave.severity = OPENMD_ERROR;
81 painCave.isFatal = 1;
82 simError();
83 }
84
85 if (!evaluator2_.isDynamic()) {
86 seleMan2_.setSelectionSet(evaluator2_.evaluate());
87 } else {
88 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
89 "dynamic selection is not allowed\n");
90 painCave.severity = OPENMD_ERROR;
91 painCave.isFatal = 1;
92 simError();
93 }
94
95 if (!evaluator3_.isDynamic()) {
96 seleMan3_.setSelectionSet(evaluator3_.evaluate());
97 } else {
98 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
99 "dynamic selection is not allowed\n");
100 painCave.severity = OPENMD_ERROR;
101 painCave.isFatal = 1;
102 simError();
103 }
104
105 int nselected1 = seleMan1_.getSelectionCount();
106 int nselected2 = seleMan2_.getSelectionCount();
107 int nselected3 = seleMan3_.getSelectionCount();
108
109 if (nselected1 != nselected2 || nselected1 != nselected3) {
110 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
111 "The number of selected Stuntdoubles must be the same\n");
112 painCave.severity = OPENMD_ERROR;
113 painCave.isFatal = 1;
114 simError();
115 }
116
117 int i;
118 int j;
119 int k;
120 StuntDouble* sd1;
121 StuntDouble* sd2;
122 StuntDouble* sd3;
123 for (sd1 = seleMan1_.beginSelected(i), sd2 = seleMan2_.beginSelected(j),
124 sd3 = seleMan3_.beginSelected(k);
125 sd1 != NULL && sd2 != NULL && sd3 != NULL;
126 sd1 = seleMan1_.nextSelected(i), sd2 = seleMan2_.nextSelected(j),
127 sd3 = seleMan3_.nextSelected(k)) {
128 tuples_.push_back(std::make_tuple(sd1, sd2, sd3));
129 }
130 }
131
132 RealType SCDElem::calcSCD(Snapshot* snapshot) {
133 Vector3d normal(0.0, 0.0, 1.0);
134 RealType scd = 0.0;
135
136 for (auto& [first, second, third] : tuples_) {
137 // Egberts B. and Berendsen H.J.C, J.Chem.Phys. 89(6), 3718-3732, 1988
138 Vector3d zAxis = third->getPos() - first->getPos();
139 if (usePeriodicBoundaryConditions_) snapshot->wrapVector(zAxis);
140 Vector3d v12 = second->getPos() - first->getPos();
141 if (usePeriodicBoundaryConditions_) snapshot->wrapVector(v12);
142 Vector3d xAxis = cross(v12, zAxis);
143 Vector3d yAxis = cross(zAxis, xAxis);
144
145 xAxis.normalize();
146 yAxis.normalize();
147 zAxis.normalize();
148 RealType cosThetaX = dot(xAxis, normal);
149 RealType sxx = 0.5 * (3 * cosThetaX * cosThetaX - 1.0);
150 RealType cosThetaY = dot(yAxis, normal);
151 RealType syy = 0.5 * (3 * cosThetaY * cosThetaY - 1.0);
152 scd += 2.0 / 3.0 * sxx + 1.0 / 3.0 * syy;
153 }
154
155 scd /= tuples_.size();
156
157 return scd;
158 }
159
160 SCDOrderParameter::SCDOrderParameter(SimInfo* info,
161 const std::string& filename,
162 const std::string& sele1,
163 const std::string& sele2,
164 const std::string& sele3) :
165 StaticAnalyser(info, filename, 1) {
166 setOutputName(getPrefix(filename) + ".scd");
167
168 scdElems_.push_back(SCDElem(info, sele1, sele2, sele3));
169 scdParam_.resize(scdElems_.size());
170 std::fill(scdParam_.begin(), scdParam_.end(), 0.0);
171 }
172
173 SCDOrderParameter::SCDOrderParameter(SimInfo* info,
174 const std::string& filename,
175 const std::string& molname,
176 int beginIndex, int endIndex) :
177 StaticAnalyser(info, filename, 1) {
178 setOutputName(getPrefix(filename) + ".scd");
179
180 assert(beginIndex >= 0 && endIndex >= 0 && beginIndex <= endIndex - 2);
181 for (int i = beginIndex; i <= endIndex - 2; ++i) {
182 std::string selectionTemplate = "select " + molname + ".";
183 std::string sele1 = selectionTemplate + OpenMD_itoa(i);
184 std::string sele2 = selectionTemplate + OpenMD_itoa(i + 1);
185 std::string sele3 = selectionTemplate + OpenMD_itoa(i + 2);
186
187 scdElems_.push_back(SCDElem(info, sele1, sele2, sele3));
188 }
189
190 scdParam_.resize(scdElems_.size());
191 std::fill(scdParam_.begin(), scdParam_.end(), 0.0);
192 }
193
194 void SCDOrderParameter::process() {
195 DumpReader reader(info_, dumpFilename_);
196 int nFrames = reader.getNFrames();
197
198 for (int i = 0; i < nFrames; i += step_) {
199 reader.readFrame(i);
200 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
201
202 for (std::size_t j = 0; j < scdElems_.size(); ++j) {
203 scdParam_[j] += scdElems_[j].calcSCD(currentSnapshot_);
204 }
205 }
206
207 int nProcessed = nFrames / step_;
208 for (std::size_t j = 0; j < scdElems_.size(); ++j) {
209 scdParam_[j] /= nProcessed;
210 }
211
212 writeSCD();
213 }
214
215 void SCDOrderParameter::writeSCD() {
216 std::ofstream os(getOutputFileName().c_str());
217 os << "#scd parameter\n";
218 for (std::size_t i = 0; i < scdElems_.size(); ++i) {
219 os << "#[column " << i + 1 << "]\t"
220 << "sele1: \"" << scdElems_[i].getSelection1() << "\",\t"
221 << "sele2: \"" << scdElems_[i].getSelection2() << "\",\t"
222 << "sele3: \"" << scdElems_[i].getSelection3() << "\"\n";
223 }
224
225 for (std::size_t i = 0; i < scdElems_.size(); ++i) {
226 os << scdParam_[i] << "\t";
227 }
228 os << std::endl;
229 }
230
231} // namespace OpenMD
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
Definition Vector3.hpp:136
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
std::string getPrefix(const std::string &str)