1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.numerics.multipole;
39
40 import static ffx.numerics.math.DoubleMath.dot;
41 import static ffx.numerics.math.DoubleMath.normalize;
42 import static ffx.numerics.math.DoubleMath.scale;
43 import static ffx.numerics.math.DoubleMath.sub;
44 import static java.util.Arrays.copyOf;
45
46
47
48
49
50
51
52
53
54
55
56
57
58 public class QIFrame {
59
60
61 private double r00, r01, r02;
62 private double r10, r11, r12;
63 private double r20, r21, r22;
64
65
66 private double ir00, ir01, ir02;
67 private double ir10, ir11, ir12;
68 private double ir20, ir21, ir22;
69
70
71
72
73
74
75 public QIFrame() {
76 setQIVector(0.0, 0.0, 1.0);
77 }
78
79
80
81
82
83
84
85
86 public QIFrame(double dx, double dy, double dz) {
87 setQIVector(dx, dy, dz);
88 }
89
90
91
92
93
94
95 public QIFrame(double[] r) {
96 setQIVector(r[0], r[1], r[2]);
97 }
98
99
100
101
102
103
104 public void setQIVector(double[] r) {
105 setQIVector(r[0], r[1], r[2]);
106 }
107
108
109
110
111
112
113
114
115 public final void setQIVector(double dx, double dy, double dz) {
116
117 double[] zAxis = {dx, dy, dz};
118
119
120 double[] xAxis = copyOf(zAxis, 3);
121 if (dy != 0.0 || dz != 0.0) {
122
123
124 xAxis[0] += 1.0;
125 } else {
126
127
128 xAxis[1] += 1.0;
129 }
130
131
132 normalize(zAxis, zAxis);
133 ir02 = zAxis[0];
134 ir12 = zAxis[1];
135 ir22 = zAxis[2];
136
137
138 double dot = dot(xAxis, zAxis);
139 scale(zAxis, dot, zAxis);
140 sub(xAxis, zAxis, xAxis);
141 normalize(xAxis, xAxis);
142 ir00 = xAxis[0];
143 ir10 = xAxis[1];
144 ir20 = xAxis[2];
145
146
147 ir01 = ir20 * ir12 - ir10 * ir22;
148 ir11 = ir00 * ir22 - ir20 * ir02;
149 ir21 = ir10 * ir02 - ir00 * ir12;
150
151
152 r00 = ir00;
153 r11 = ir11;
154 r22 = ir22;
155 r01 = ir10;
156 r02 = ir20;
157 r10 = ir01;
158 r12 = ir21;
159 r20 = ir02;
160 r21 = ir12;
161 }
162
163
164
165
166
167
168
169
170 public void setAndRotate(double[] r, PolarizableMultipole mI, PolarizableMultipole mK) {
171 setAndRotate(r[0], r[1], r[2], mI, mK);
172 }
173
174
175
176
177
178
179
180
181
182
183 public void setAndRotate(double dx, double dy, double dz,
184 PolarizableMultipole mI, PolarizableMultipole mK) {
185 setQIVector(dx, dy, dz);
186 rotatePolarizableMultipole(mI);
187 rotatePolarizableMultipole(mK);
188 }
189
190
191
192
193
194
195 public void rotatePolarizableMultipole(PolarizableMultipole m) {
196 rotatePermanentMultipole(m);
197 rotateInducedDipoles(m);
198 }
199
200
201
202
203
204
205 public void rotatePermanentMultipole(PolarizableMultipole m) {
206
207 double dx = m.dx;
208 double dy = m.dy;
209 double dz = m.dz;
210 m.dx = r00 * dx + r01 * dy + r02 * dz;
211 m.dy = r10 * dx + r11 * dy + r12 * dz;
212 m.dz = r20 * dx + r21 * dy + r22 * dz;
213
214
215 double qxx = m.qxx;
216 double qyy = m.qyy;
217 double qzz = m.qzz;
218
219 double qxy = m.qxy * 0.5;
220 double qxz = m.qxz * 0.5;
221 double qyz = m.qyz * 0.5;
222
223 m.qxx = r00 * (r00 * qxx + r01 * qxy + r02 * qxz)
224 + r01 * (r00 * qxy + r01 * qyy + r02 * qyz)
225 + r02 * (r00 * qxz + r01 * qyz + r02 * qzz);
226
227 m.qxy = r00 * (r10 * qxx + r11 * qxy + r12 * qxz)
228 + r01 * (r10 * qxy + r11 * qyy + r12 * qyz)
229 + r02 * (r10 * qxz + r11 * qyz + r12 * qzz);
230 m.qxy *= 2.0;
231
232 m.qxz = r00 * (r20 * qxx + r21 * qxy + r22 * qxz)
233 + r01 * (r20 * qxy + r21 * qyy + r22 * qyz)
234 + r02 * (r20 * qxz + r21 * qyz + r22 * qzz);
235 m.qxz *= 2.0;
236
237 m.qyy = r10 * (r10 * qxx + r11 * qxy + r12 * qxz)
238 + r11 * (r10 * qxy + r11 * qyy + r12 * qyz)
239 + r12 * (r10 * qxz + r11 * qyz + r12 * qzz);
240
241 m.qyz = r10 * (r20 * qxx + r21 * qxy + r22 * qxz)
242 + r11 * (r20 * qxy + r21 * qyy + r22 * qyz)
243 + r12 * (r20 * qxz + r21 * qyz + r22 * qzz);
244 m.qyz *= 2.0;
245
246 m.qzz = r20 * (r20 * qxx + r21 * qxy + r22 * qxz)
247 + r21 * (r20 * qxy + r21 * qyy + r22 * qyz)
248 + r22 * (r20 * qxz + r21 * qyz + r22 * qzz);
249 }
250
251
252
253
254
255
256 public void rotateInducedDipoles(PolarizableMultipole m) {
257 double dx = m.ux;
258 double dy = m.uy;
259 double dz = m.uz;
260 m.ux = r00 * dx + r01 * dy + r02 * dz;
261 m.uy = r10 * dx + r11 * dy + r12 * dz;
262 m.uz = r20 * dx + r21 * dy + r22 * dz;
263 dx = m.px;
264 dy = m.py;
265 dz = m.pz;
266 m.px = r00 * dx + r01 * dy + r02 * dz;
267 m.py = r10 * dx + r11 * dy + r12 * dz;
268 m.pz = r20 * dx + r21 * dy + r22 * dz;
269
270 m.sx = (m.ux + m.px) * 0.5;
271 m.sy = (m.uy + m.py) * 0.5;
272 m.sz = (m.uz + m.pz) * 0.5;
273 }
274
275
276
277
278
279
280 public void toGlobal(double[] v) {
281 double vx = v[0];
282 double vy = v[1];
283 double vz = v[2];
284
285 v[0] = ir00 * vx + ir01 * vy + ir02 * vz;
286
287 v[1] = ir10 * vx + ir11 * vy + ir12 * vz;
288
289 v[2] = ir20 * vx + ir21 * vy + ir22 * vz;
290 }
291 }