OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
ContactAngle2.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/sequentialProps/ContactAngle2.hpp"
46
47#include <algorithm>
48#include <functional>
49#include <sstream>
50
51#include "io/DumpReader.hpp"
52#include "math/Eigenvalue.hpp"
54#include "utils/Constants.hpp"
55#include "utils/simError.h"
56
57namespace OpenMD {
58
59 ContactAngle2::ContactAngle2(SimInfo* info, const std::string& filename,
60 const std::string& sele1,
61 const std::string& sele2, RealType solidZ,
62 RealType centroidX, RealType centroidY,
63 RealType threshDens, RealType bufferLength,
64 int nrbins, int nzbins) :
65 SequentialAnalyzer(info, filename, sele1, sele2),
66 solidZ_(solidZ), centroidX_(centroidX), centroidY_(centroidY),
67 threshDens_(threshDens), bufferLength_(bufferLength), nRBins_(nrbins),
68 nZBins_(nzbins) {
69 setOutputName(getPrefix(filename) + ".ca2");
70
71 std::stringstream params;
72 params << " referenceZ = " << solidZ_ << ", centroid = (" << centroidX_
73 << ", " << centroidY_ << ")"
74 << ", threshDens = " << threshDens_
75 << ", bufferLength = " << bufferLength_ << ", nbins = " << nRBins_
76 << ", nbins_z = " << nZBins_;
77
78 const std::string paramString = params.str();
79 setParameterString(paramString);
80 }
81
82 void ContactAngle2::doFrame(int) {
83 StuntDouble* sd;
84 int i;
85
86 // set up the bins for density analysis
87
89 RealType len = std::min(hmat(0, 0), hmat(1, 1));
90 RealType zLen = hmat(2, 2);
91
92 RealType dr = len / (RealType)nRBins_;
93 RealType dz = zLen / (RealType)nZBins_;
94
95 std::vector<std::vector<RealType>> histo;
96 histo.resize(nRBins_);
97 for (unsigned int i = 0; i < histo.size(); ++i) {
98 histo[i].resize(nZBins_);
99 std::fill(histo[i].begin(), histo[i].end(), 0.0);
100 }
101
102 if (evaluator1_.isDynamic()) {
103 seleMan1_.setSelectionSet(evaluator1_.evaluate());
104 }
105
106 Vector3d com(centroidX_, centroidY_, solidZ_);
107
108 // now that we have the centroid, we can make cylindrical density maps
109 Vector3d pos;
110 RealType r;
111 RealType z;
112
113 for (sd = seleMan1_.beginSelected(i); sd != NULL;
114 sd = seleMan1_.nextSelected(i)) {
115 pos = sd->getPos() - com;
116
117 // r goes from zero upwards
118 r = sqrt(pow(pos.x(), 2) + pow(pos.y(), 2));
119 // z is possibly symmetric around 0
120 z = pos.z();
121
122 int whichRBin = int(r / dr);
123 int whichZBin = int((zLen / 2.0 + z) / dz);
124
125 if ((whichRBin < int(nRBins_)) && (whichZBin >= 0) &&
126 (whichZBin < int(nZBins_))) {
127 histo[whichRBin][whichZBin] += sd->getMass();
128 }
129 }
130
131 for (unsigned int i = 0; i < histo.size(); ++i) {
132 RealType rL = i * dr;
133 RealType rU = rL + dr;
134 RealType volSlice = Constants::PI * dz * ((rU * rU) - (rL * rL));
135
136 for (unsigned int j = 0; j < histo[i].size(); ++j) {
137 histo[i][j] *= Constants::densityConvert / volSlice;
138 }
139 }
140
141 std::vector<Vector<RealType, 2>> points;
142 points.clear();
143
144 for (unsigned int j = 0; j < nZBins_; ++j) {
145 // The z coordinates were measured relative to the selection
146 // center of mass. However, we're interested in the elevation
147 // above the solid surface. Also, the binning was done around
148 // zero with enough bins to cover the zLength of the box:
149
150 RealType thez = com.z() - solidZ_ - zLen / 2.0 + dz * (j + 0.5);
151 bool aboveThresh = false;
152 bool foundThresh = false;
153 int rloc = 0;
154
155 for (std::size_t i = 0; i < nRBins_; ++i) {
156 if (histo[i][j] >= threshDens_) aboveThresh = true;
157
158 if (aboveThresh && (histo[i][j] <= threshDens_)) {
159 rloc = i;
160 foundThresh = true;
161 aboveThresh = false;
162 }
163 }
164 if (foundThresh) {
165 Vector<RealType, 2> point;
166 point[0] = dr * (rloc + 0.5);
167 point[1] = thez;
168
169 if (thez > bufferLength_) { points.push_back(point); }
170 }
171 }
172
173 int numPoints = points.size();
174
175 // Compute the average of the data points.
176 Vector<RealType, 2> average = points[0];
177 int i0;
178 for (i0 = 1; i0 < numPoints; ++i0) {
179 average += points[i0];
180 }
181 RealType invNumPoints = ((RealType)1) / (RealType)numPoints;
182 average *= invNumPoints;
183
184 DynamicRectMatrix<RealType> mat(4, 4);
185 int row, col;
186 for (row = 0; row < 4; ++row) {
187 for (col = 0; col < 4; ++col) {
188 mat(row, col) = 0.0;
189 }
190 }
191 for (int i = 0; i < numPoints; ++i) {
192 RealType x = points[i][0];
193 RealType y = points[i][1];
194 RealType x2 = x * x;
195 RealType y2 = y * y;
196 RealType xy = x * y;
197 RealType r2 = x2 + y2;
198 RealType xr2 = x * r2;
199 RealType yr2 = y * r2;
200 RealType r4 = r2 * r2;
201
202 mat(0, 1) += x;
203 mat(0, 2) += y;
204 mat(0, 3) += r2;
205 mat(1, 1) += x2;
206 mat(1, 2) += xy;
207 mat(1, 3) += xr2;
208 mat(2, 2) += y2;
209 mat(2, 3) += yr2;
210 mat(3, 3) += r4;
211 }
212 mat(0, 0) = (RealType)numPoints;
213
214 for (row = 0; row < 4; ++row) {
215 for (col = 0; col < row; ++col) {
216 mat(row, col) = mat(col, row);
217 }
218 }
219
220 for (row = 0; row < 4; ++row) {
221 for (col = 0; col < 4; ++col) {
222 mat(row, col) *= invNumPoints;
223 }
224 }
225
226 JAMA::Eigenvalue<RealType> eigensystem(mat);
227 DynamicRectMatrix<RealType> evects(4, 4);
228 DynamicVector<RealType> evals(4);
229
230 eigensystem.getRealEigenvalues(evals);
231 eigensystem.getV(evects);
232
233 DynamicVector<RealType> evector = evects.getColumn(0);
234 RealType inv = ((RealType)1) / evector[3]; // beware zero divide
235 RealType coeff[3];
236 for (row = 0; row < 3; ++row) {
237 coeff[row] = inv * evector[row];
238 }
239
240 Vector<RealType, 2> center;
241
242 center[0] = -((RealType)0.5) * coeff[1];
243 center[1] = -((RealType)0.5) * coeff[2];
244 RealType radius =
245 sqrt(fabs(center[0] * center[0] + center[1] * center[1] - coeff[0]));
246
247 int i1;
248 for (i1 = 0; i1 < 100; ++i1) {
249 // Update the iterates.
250 Vector<RealType, 2> current = center;
251
252 // Compute average L, dL/da, dL/db.
253 RealType lenAverage = (RealType)0;
254 Vector<RealType, 2> derLenAverage = Vector<RealType, 2>(0.0);
255 for (i0 = 0; i0 < numPoints; ++i0) {
256 Vector<RealType, 2> diff = points[i0] - center;
257 RealType length = diff.length();
258 if (length > 1e-6) {
259 lenAverage += length;
260 RealType invLength = ((RealType)1) / length;
261 derLenAverage -= invLength * diff;
262 }
263 }
264 lenAverage *= invNumPoints;
265 derLenAverage *= invNumPoints;
266
267 center = average + lenAverage * derLenAverage;
268 radius = lenAverage;
269
270 Vector<RealType, 2> diff = center - current;
271 if (fabs(diff[0]) <= 1e-6 && fabs(diff[1]) <= 1e-6) { break; }
272 }
273
274 RealType zCen = center[1];
275 RealType rDrop = radius;
276 RealType ca;
277
278 if (fabs(zCen) > rDrop) {
279 ca = 180.0;
280 } else {
281 ca = 90.0 + asin(zCen / rDrop) * (180.0 / Constants::PI);
282 }
283
284 values_.push_back(ca);
285 }
286} // namespace OpenMD
Computes eigenvalues and eigenvectors of a real (non-complex) matrix.
bool isDynamic()
Tests if the result from evaluation of script is dynamic.
StuntDouble * nextSelected(int &i)
Finds the next selected StuntDouble in the selection.
StuntDouble * beginSelected(int &i)
Finds the first selected StuntDouble in the selection.
"applications/sequentialProps/SequentialAnalyzer"
One of the heavy-weight classes of OpenMD, SimInfo maintains objects and variables relating to the cu...
Definition SimInfo.hpp:93
SnapshotManager * getSnapshotManager()
Returns the snapshot manager.
Definition SimInfo.hpp:248
Mat3x3d getHmat()
Returns the H-Matrix.
Definition Snapshot.cpp:214
Snapshot * getCurrentSnapshot()
Returns the pointer of current snapshot.
"Don't move, or you're dead! Stand up! Captain, we've got them!"
RealType getMass()
Returns the mass of this stuntDouble.
Vector3d getPos()
Returns the current position of this stuntDouble.
Real & z()
Returns reference of the third element of Vector3.
Definition Vector3.hpp:120
Real & x()
Returns reference of the first element of Vector3.
Definition Vector3.hpp:96
Real & y()
Returns reference of the second element of Vector3.
Definition Vector3.hpp:108
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
std::string getPrefix(const std::string &str)