OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
HydroProp.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 "hydrodynamics/HydroProp.hpp"
49
50#include "math/CholeskyDecomposition.hpp"
52#include "utils/simError.h"
53
54namespace OpenMD {
55
56 HydroProp::HydroProp() : hasCOR_(false), hasXi_(false), hasS_(false) {}
57
58 HydroProp::HydroProp(Vector3d cor, Mat6x6d Xi) :
59 cor_(cor), Xi_(Xi), hasCOR_(true), hasXi_(true), hasS_(false) {}
60
61 void HydroProp::complete() {
62 if (hasXi_) {
63 CholeskyDecomposition(Xi_, S_);
64 hasS_ = true;
65 } else {
66 snprintf(
67 painCave.errMsg, MAX_SIM_ERROR_MSG_LENGTH,
68 "HydroProp was asked to complete without a Resistance Tensor.\n");
69 painCave.severity = OPENMD_ERROR;
70 painCave.isFatal = 1;
71 simError();
72 }
73 }
74
75 Mat6x6d HydroProp::getS() {
76 if (!hasS_) { complete(); }
77 return S_;
78 }
79
80 Mat3x3d HydroProp::getXitt() {
81 Mat3x3d Xitt;
82 Xi_.getSubMatrix(0, 0, Xitt);
83 return Xitt;
84 }
85 Mat3x3d HydroProp::getXirt() {
86 Mat3x3d Xirt;
87 Xi_.getSubMatrix(0, 3, Xirt);
88 return Xirt;
89 }
90 Mat3x3d HydroProp::getXitr() {
91 Mat3x3d Xitr;
92 Xi_.getSubMatrix(3, 0, Xitr);
93 return Xitr;
94 }
95 Mat3x3d HydroProp::getXirr() {
96 Mat3x3d Xirr;
97 Xi_.getSubMatrix(3, 3, Xirr);
98 return Xirr;
99 }
100
101 Mat6x6d HydroProp::getDiffusionTensor(RealType temperature) {
102 Mat6x6d XiCopy = Xi_;
103 Mat6x6d D;
104 invertMatrix(XiCopy, D);
105 RealType kt = Constants::kb * temperature; // in kcal mol^-1
106 D *= kt; // now in angstroms^2 fs^-1 (at least for Trans-trans)
107 return D;
108 }
109
110 Mat6x6d HydroProp::getResistanceTensorAtPos(Vector3d pos) {
111 // Vector from reference point to center of resistance = cor_
112 // Vector from reference point to new location = pos
113 // Vector from center of resistance to new location = pos - cor_
114 Vector3d cp = pos - cor_;
115 Mat3x3d U;
116 U.setupSkewMat(cp);
117
118 Mat3x3d Xitt = getXitt();
119 Mat3x3d Xitr = getXitr();
120 Mat3x3d Xirr = getXirr();
121
122 Mat3x3d Xipostt;
123 Mat3x3d Xiposrr;
124 Mat3x3d Xipostr;
125
126 // Resistance tensors at the new location
127 Xipostt = Xitt;
128 Xipostr = (Xitr - U * Xitt);
129 Xiposrr = Xirr - U * Xitt * U + Xitr * U - U * Xitr.transpose();
130
131 Mat6x6d Xipos;
132 Xipos.setSubMatrix(0, 0, Xipostt);
133 Xipos.setSubMatrix(0, 3, Xipostr.transpose());
134 Xipos.setSubMatrix(3, 0, Xipostr);
135 Xipos.setSubMatrix(3, 3, Xiposrr);
136 return Xipos;
137 }
138
139 Mat6x6d HydroProp::getDiffusionTensorAtPos(Vector3d pos,
140 RealType temperature) {
141 // Vector from reference point to center of resistance = cor_
142 // Vector from reference point to new location = pos
143 // Vector from center of resistance to new location = pos - cor_
144
145 Vector3d cp = pos - cor_;
146 Mat3x3d U;
147 U.setupSkewMat(cp);
148
149 Mat6x6d D = getDiffusionTensor(temperature);
150
151 Mat3x3d Dtt;
152 Mat3x3d Dtr;
153 Mat3x3d Drr;
154
155 D.getSubMatrix(0, 0, Dtt);
156 D.getSubMatrix(3, 0, Dtr);
157 D.getSubMatrix(3, 3, Drr);
158
159 // calculate Diffusion Tensor at new location
160 Mat3x3d Dpostt; // translational diffusion tensor at new location
161 Mat3x3d Dpostr; // rotational diffusion tensor at new location
162 Mat3x3d Dposrr; // translation-rotation coupling diffusion tensor
163 // at new location
164
165 Dpostt = Dtt - U * Drr * U + Dtr.transpose() * U - U * Dtr;
166 Dposrr = Drr;
167 Dpostr = Dtr + Drr * U;
168
169 Mat6x6d Dpos;
170 Dpos.setSubMatrix(0, 0, Dpostt);
171 Dpos.setSubMatrix(0, 3, Dpostr.transpose());
172 Dpos.setSubMatrix(3, 0, Dpostr);
173 Dpos.setSubMatrix(3, 3, Dposrr);
174 return Dpos;
175 }
176
177 Vector3d HydroProp::getCenterOfDiffusion(RealType temperature) {
178 // First get the Diffusion tensor at the origin of the coordinate system:
179
180 Vector3d origin(0.0);
181 Mat6x6d Do = getDiffusionTensorAtPos(origin, temperature);
182
183 Mat3x3d Dotr;
184 Mat3x3d Dorr;
185
186 Do.getSubMatrix(3, 0, Dotr);
187 Do.getSubMatrix(3, 3, Dorr);
188
189 Mat3x3d tmp;
190 Vector3d tmpVec;
191
192 // Find center of diffusion
193 tmp(0, 0) = Dorr(1, 1) + Dorr(2, 2);
194 tmp(0, 1) = -Dorr(0, 1);
195 tmp(0, 2) = -Dorr(0, 2);
196 tmp(1, 0) = -Dorr(0, 1);
197 tmp(1, 1) = Dorr(0, 0) + Dorr(2, 2);
198 tmp(1, 2) = -Dorr(1, 2);
199 tmp(2, 0) = -Dorr(0, 2);
200 tmp(2, 1) = -Dorr(1, 2);
201 tmp(2, 2) = Dorr(1, 1) + Dorr(0, 0);
202
203 // Vector3d tmpVec;
204 tmpVec[0] = Dotr(1, 2) - Dotr(2, 1);
205 tmpVec[1] = Dotr(2, 0) - Dotr(0, 2);
206 tmpVec[2] = Dotr(0, 1) - Dotr(1, 0);
207
208 // center of difussion
209 Vector3d cod = tmp.inverse() * tmpVec;
210 return cod;
211 }
212
213 Mat3x3d HydroProp::getPitchMatrix() {
214 Mat3x3d P;
215 P = -getXitt().inverse() * getXirt();
216 return P;
217 }
218
219 RealType HydroProp::getScalarPitch() {
220 Mat3x3d P = getPitchMatrix();
221 Vector3d evals;
222 Mat3x3d evects;
223 Mat3x3d::diagonalize(P, evals, evects);
224 RealType pScalar(0.0);
225
226 for (int i = 0; i < 3; i++) {
227 pScalar += pow(evals[i], 2);
228 }
229 pScalar /= 3.0;
230
231 return sqrt(pScalar);
232 }
233
234 void HydroProp::pitchAxes(Mat3x3d& pitchAxes, Vector3d& pitches,
235 RealType& pitchScalar) {
236 Mat3x3d P = getPitchMatrix();
237
238 Mat3x3d::diagonalize(P, pitches, pitchAxes);
239
240 pitchScalar = 0.0;
241 for (int i = 0; i < 3; i++) {
242 pitchScalar += pow(pitches[i], 2);
243 }
244 pitchScalar /= 3.0;
245
246 pitchScalar = sqrt(pitchScalar);
247 }
248
249 Vector3d HydroProp::getCenterOfPitch() {
250 Mat3x3d P = getPitchMatrix();
251 Vector3d cop;
252 cop[0] = 0.5 * (P(1, 2) - P(2, 1));
253 cop[1] = 0.5 * (P(2, 0) - P(0, 2));
254 cop[2] = 0.5 * (P(0, 1) - P(1, 0));
255 // Assume Xi_ was stored at center of resistance, so center of
256 // pitch is returned relative to origin if center of resistance is
257 // not the origin:
258 return (cor_ + cop);
259 }
260
261} // namespace OpenMD
SquareMatrix3< Real > inverse() const
Sets the value of this matrix to the inverse of itself.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
bool invertMatrix(MatrixType &A, MatrixType &AI)
Invert input square matrix A into matrix AI.
Definition LU.hpp:101