OpenMD 3.2
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 following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48#include "applications/staticProps/SCDOrderParameter.hpp"
49
50#include <string>
51#include <tuple>
52#include <vector>
53
54#include "io/DumpReader.hpp"
56#include "utils/simError.h"
57
58namespace OpenMD {
59
60 SCDElem::SCDElem(SimInfo* info, const std::string& sele1,
61 const std::string& sele2, const std::string& sele3) :
62 sele1_(sele1),
63 sele2_(sele2), sele3_(sele3) {
64 usePeriodicBoundaryConditions_ =
65 info->getSimParams()->getUsePeriodicBoundaryConditions();
66
67 SelectionManager seleMan1_(info);
68 SelectionManager seleMan2_(info);
69 SelectionManager seleMan3_(info);
70 SelectionEvaluator evaluator1_(info);
71 SelectionEvaluator evaluator2_(info);
72 SelectionEvaluator evaluator3_(info);
73
74 evaluator1_.loadScriptString(sele1_);
75 evaluator2_.loadScriptString(sele2_);
76 evaluator3_.loadScriptString(sele3_);
77
78 if (!evaluator1_.isDynamic()) {
79 seleMan1_.setSelectionSet(evaluator1_.evaluate());
80 } else {
81 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
82 "dynamic selection is not allowed\n");
83 painCave.severity = OPENMD_ERROR;
84 painCave.isFatal = 1;
85 simError();
86 }
87
88 if (!evaluator2_.isDynamic()) {
89 seleMan2_.setSelectionSet(evaluator2_.evaluate());
90 } else {
91 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
92 "dynamic selection is not allowed\n");
93 painCave.severity = OPENMD_ERROR;
94 painCave.isFatal = 1;
95 simError();
96 }
97
98 if (!evaluator3_.isDynamic()) {
99 seleMan3_.setSelectionSet(evaluator3_.evaluate());
100 } else {
101 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
102 "dynamic selection is not allowed\n");
103 painCave.severity = OPENMD_ERROR;
104 painCave.isFatal = 1;
105 simError();
106 }
107
108 int nselected1 = seleMan1_.getSelectionCount();
109 int nselected2 = seleMan2_.getSelectionCount();
110 int nselected3 = seleMan3_.getSelectionCount();
111
112 if (nselected1 != nselected2 || nselected1 != nselected3) {
113 snprintf(painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
114 "The number of selected Stuntdoubles must be the same\n");
115 painCave.severity = OPENMD_ERROR;
116 painCave.isFatal = 1;
117 simError();
118 }
119
120 int i;
121 int j;
122 int k;
123 StuntDouble* sd1;
124 StuntDouble* sd2;
125 StuntDouble* sd3;
126 for (sd1 = seleMan1_.beginSelected(i), sd2 = seleMan2_.beginSelected(j),
127 sd3 = seleMan3_.beginSelected(k);
128 sd1 != NULL && sd2 != NULL && sd3 != NULL;
129 sd1 = seleMan1_.nextSelected(i), sd2 = seleMan2_.nextSelected(j),
130 sd3 = seleMan3_.nextSelected(k)) {
131 tuples_.push_back(std::make_tuple(sd1, sd2, sd3));
132 }
133 }
134
135 RealType SCDElem::calcSCD(Snapshot* snapshot) {
136 Vector3d normal(0.0, 0.0, 1.0);
137 RealType scd = 0.0;
138
139 for (auto& [first, second, third] : tuples_) {
140 // Egberts B. and Berendsen H.J.C, J.Chem.Phys. 89(6), 3718-3732, 1988
141 Vector3d zAxis = third->getPos() - first->getPos();
142 if (usePeriodicBoundaryConditions_) snapshot->wrapVector(zAxis);
143 Vector3d v12 = second->getPos() - first->getPos();
144 if (usePeriodicBoundaryConditions_) snapshot->wrapVector(v12);
145 Vector3d xAxis = cross(v12, zAxis);
146 Vector3d yAxis = cross(zAxis, xAxis);
147
148 xAxis.normalize();
149 yAxis.normalize();
150 zAxis.normalize();
151 RealType cosThetaX = dot(xAxis, normal);
152 RealType sxx = 0.5 * (3 * cosThetaX * cosThetaX - 1.0);
153 RealType cosThetaY = dot(yAxis, normal);
154 RealType syy = 0.5 * (3 * cosThetaY * cosThetaY - 1.0);
155 scd += 2.0 / 3.0 * sxx + 1.0 / 3.0 * syy;
156 }
157
158 scd /= tuples_.size();
159
160 return scd;
161 }
162
163 SCDOrderParameter::SCDOrderParameter(SimInfo* info,
164 const std::string& filename,
165 const std::string& sele1,
166 const std::string& sele2,
167 const std::string& sele3) :
168 StaticAnalyser(info, filename, 1) {
169 setOutputName(getPrefix(filename) + ".scd");
170
171 scdElems_.push_back(SCDElem(info, sele1, sele2, sele3));
172 scdParam_.resize(scdElems_.size());
173 std::fill(scdParam_.begin(), scdParam_.end(), 0.0);
174 }
175
176 SCDOrderParameter::SCDOrderParameter(SimInfo* info,
177 const std::string& filename,
178 const std::string& molname,
179 int beginIndex, int endIndex) :
180 StaticAnalyser(info, filename, 1) {
181 setOutputName(getPrefix(filename) + ".scd");
182
183 assert(beginIndex >= 0 && endIndex >= 0 && beginIndex <= endIndex - 2);
184 for (int i = beginIndex; i <= endIndex - 2; ++i) {
185 std::string selectionTemplate = "select " + molname + ".";
186 std::string sele1 = selectionTemplate + OpenMD_itoa(i);
187 std::string sele2 = selectionTemplate + OpenMD_itoa(i + 1);
188 std::string sele3 = selectionTemplate + OpenMD_itoa(i + 2);
189
190 scdElems_.push_back(SCDElem(info, sele1, sele2, sele3));
191 }
192
193 scdParam_.resize(scdElems_.size());
194 std::fill(scdParam_.begin(), scdParam_.end(), 0.0);
195 }
196
197 void SCDOrderParameter::process() {
198 DumpReader reader(info_, dumpFilename_);
199 int nFrames = reader.getNFrames();
200
201 for (int i = 0; i < nFrames; i += step_) {
202 reader.readFrame(i);
203 currentSnapshot_ = info_->getSnapshotManager()->getCurrentSnapshot();
204
205 for (std::size_t j = 0; j < scdElems_.size(); ++j) {
206 scdParam_[j] += scdElems_[j].calcSCD(currentSnapshot_);
207 }
208 }
209
210 int nProcessed = nFrames / step_;
211 for (std::size_t j = 0; j < scdElems_.size(); ++j) {
212 scdParam_[j] /= nProcessed;
213 }
214
215 writeSCD();
216 }
217
218 void SCDOrderParameter::writeSCD() {
219 std::ofstream os(getOutputFileName().c_str());
220 os << "#scd parameter\n";
221 for (std::size_t i = 0; i < scdElems_.size(); ++i) {
222 os << "#[column " << i + 1 << "]\t"
223 << "sele1: \"" << scdElems_[i].getSelection1() << "\",\t"
224 << "sele2: \"" << scdElems_[i].getSelection2() << "\",\t"
225 << "sele3: \"" << scdElems_[i].getSelection3() << "\"\n";
226 }
227
228 for (std::size_t i = 0; i < scdElems_.size(); ++i) {
229 os << scdParam_[i] << "\t";
230 }
231 os << std::endl;
232 }
233
234} // namespace OpenMD
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:96
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:139
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
std::string getPrefix(const std::string &str)