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 jdk.incubator.vector.DoubleVector;
41 import jdk.incubator.vector.VectorMask;
42
43 import static java.util.Arrays.copyOf;
44
45
46
47
48
49
50
51
52
53
54
55
56
57 public class QIFrameSIMD {
58
59
60 private DoubleVector r00Vec, r01Vec, r02Vec;
61 private DoubleVector r10Vec, r11Vec, r12Vec;
62 private DoubleVector r20Vec, r21Vec, r22Vec;
63
64
65 private DoubleVector ir00Vec, ir01Vec, ir02Vec;
66 private DoubleVector ir10Vec, ir11Vec, ir12Vec;
67 private DoubleVector ir20Vec, ir21Vec, ir22Vec;
68
69
70
71
72
73
74 public QIFrameSIMD() {
75 DoubleVector zero = DoubleVector.broadcast(DoubleVector.SPECIES_PREFERRED, 0.0);
76 setQIVector(zero, zero, zero);
77 }
78
79
80
81
82 public QIFrameSIMD(DoubleVector dx, DoubleVector dy, DoubleVector dz) {
83 setQIVector(dx, dy, dz);
84 }
85
86
87
88
89
90
91 public QIFrameSIMD(DoubleVector[] r) {
92 setQIVector(r[0], r[1], r[2]);
93 }
94
95
96
97
98
99
100 public void setQIVector(DoubleVector[] r) {
101 setQIVector(r[0], r[1], r[2]);
102 }
103
104
105
106
107
108
109
110
111 public final void setQIVector(DoubleVector dx, DoubleVector dy, DoubleVector dz) {
112
113 DoubleVector[] zAxis = {dx, dy, dz};
114
115
116 DoubleVector[] xAxis = copyOf(zAxis, 3);
117
118
119 VectorMask<Double> qiVectorIsXAxis = dz.eq(0.0).and(dy.eq(0.0));
120
121 xAxis[1] = xAxis[1].add(1.0, qiVectorIsXAxis);
122
123 xAxis[0] = xAxis[0].add(1.0, qiVectorIsXAxis.not());
124
125
126 normalizeVec(zAxis, zAxis);
127 ir02Vec = zAxis[0];
128 ir12Vec = zAxis[1];
129 ir22Vec = zAxis[2];
130
131
132 DoubleVector dot = dotVec(xAxis, zAxis);
133 scaleVec(zAxis, dot, zAxis);
134 subVec(xAxis, zAxis, xAxis);
135 normalizeVec(xAxis, xAxis);
136 ir00Vec = xAxis[0];
137 ir10Vec = xAxis[1];
138 ir20Vec = xAxis[2];
139
140
141 ir01Vec = ir20Vec.mul(ir12Vec).sub(ir10Vec.mul(ir22Vec));
142 ir11Vec = ir00Vec.mul(ir22Vec).sub(ir20Vec.mul(ir02Vec));
143 ir21Vec = ir10Vec.mul(ir02Vec).sub(ir00Vec.mul(ir12Vec));
144
145
146 r00Vec = ir00Vec;
147 r11Vec = ir11Vec;
148 r22Vec = ir22Vec;
149 r01Vec = ir10Vec;
150 r02Vec = ir20Vec;
151 r10Vec = ir01Vec;
152 r12Vec = ir21Vec;
153 r20Vec = ir02Vec;
154 r21Vec = ir12Vec;
155 }
156
157
158
159
160
161
162
163
164 public static DoubleVector dotVec(DoubleVector[] a, DoubleVector[] b) {
165 return a[0].fma(b[0], a[1].fma(b[1], a[2].mul(b[2])));
166 }
167
168
169
170
171
172
173
174
175
176 public static DoubleVector[] scaleVec(DoubleVector[] a, DoubleVector scale, DoubleVector[] ret) {
177 ret[0] = a[0].mul(scale);
178 ret[1] = a[1].mul(scale);
179 ret[2] = a[2].mul(scale);
180 return ret;
181 }
182
183
184
185
186
187
188
189
190
191 public static DoubleVector[] subVec(DoubleVector[] a, DoubleVector[] b, DoubleVector[] ret) {
192 ret[0] = a[0].sub(b[0]);
193 ret[1] = a[1].sub(b[1]);
194 ret[2] = a[2].sub(b[2]);
195 return ret;
196 }
197
198
199
200
201
202
203
204
205 public static DoubleVector[] normalizeVec(DoubleVector[] n, DoubleVector[] ret) {
206 return scaleVec(n, DoubleVector.broadcast(DoubleVector.SPECIES_PREFERRED, 1.0).div(dotVec(n, n).sqrt()), ret);
207 }
208
209
210
211
212
213
214
215
216 public void setAndRotate(DoubleVector[] r, PolarizableMultipoleSIMD mI, PolarizableMultipoleSIMD mK) {
217 setAndRotate(r[0], r[1], r[2], mI, mK);
218 }
219
220
221
222
223
224
225
226
227
228
229 public void setAndRotate(DoubleVector dx, DoubleVector dy, DoubleVector dz,
230 PolarizableMultipoleSIMD mI, PolarizableMultipoleSIMD mK) {
231 setQIVector(dx, dy, dz);
232 rotatePolarizableMultipole(mI);
233 rotatePolarizableMultipole(mK);
234 }
235
236
237
238
239
240
241 public void rotatePolarizableMultipole(PolarizableMultipoleSIMD m) {
242 rotatePermanentMultipole(m);
243 rotateInducedDipoles(m);
244 }
245
246
247
248
249
250
251 public void rotatePermanentMultipole(PolarizableMultipoleSIMD m) {
252
253 DoubleVector dx = m.dx;
254 DoubleVector dy = m.dy;
255 DoubleVector dz = m.dz;
256 m.dx = r00Vec.mul(dx).add(r01Vec.mul(dy)).add(r02Vec.mul(dz));
257 m.dy = r10Vec.mul(dx).add(r11Vec.mul(dy)).add(r12Vec.mul(dz));
258 m.dz = r20Vec.mul(dx).add(r21Vec.mul(dy)).add(r22Vec.mul(dz));
259
260
261 DoubleVector qxx = m.qxx;
262 DoubleVector qyy = m.qyy;
263 DoubleVector qzz = m.qzz;
264
265 DoubleVector qxy = m.qxy.mul(0.5);
266 DoubleVector qxz = m.qxz.mul(0.5);
267 DoubleVector qyz = m.qyz.mul(0.5);
268
269 m.qxx = r00Vec.mul(r00Vec.mul(qxx).add(r01Vec.mul(qxy)).add(r02Vec.mul(qxz)))
270 .add(r01Vec.mul((r00Vec.mul(qxy).add(r01Vec.mul(qyy)).add(r02Vec.mul(qyz)))))
271 .add(r02Vec.mul((r00Vec.mul(qxz).add(r01Vec.mul(qyz)).add(r02Vec.mul(qzz)))));
272
273 m.qxy = r00Vec.mul(r10Vec.mul(qxx).add(r11Vec.mul(qxy)).add(r12Vec.mul(qxz)))
274 .add(r01Vec.mul((r10Vec.mul(qxy).add(r11Vec.mul(qyy)).add(r12Vec.mul(qyz)))))
275 .add(r02Vec.mul((r10Vec.mul(qxz).add(r11Vec.mul(qyz)).add(r12Vec.mul(qzz)))));
276 m.qxy = m.qxy.mul(2.0);
277
278 m.qxz = r00Vec.mul(r20Vec.mul(qxx).add(r21Vec.mul(qxy)).add(r22Vec.mul(qxz)))
279 .add(r01Vec.mul((r20Vec.mul(qxy).add(r21Vec.mul(qyy)).add(r22Vec.mul(qyz)))))
280 .add(r02Vec.mul((r20Vec.mul(qxz).add(r21Vec.mul(qyz)).add(r22Vec.mul(qzz)))));
281 m.qxz = m.qxz.mul(2.0);
282
283 m.qyy = r10Vec.mul(r10Vec.mul(qxx).add(r11Vec.mul(qxy)).add(r12Vec.mul(qxz)))
284 .add(r11Vec.mul((r10Vec.mul(qxy).add(r11Vec.mul(qyy)).add(r12Vec.mul(qyz)))))
285 .add(r12Vec.mul((r10Vec.mul(qxz).add(r11Vec.mul(qyz)).add(r12Vec.mul(qzz)))));
286
287 m.qyz = r10Vec.mul(r20Vec.mul(qxx).add(r21Vec.mul(qxy)).add(r22Vec.mul(qxz)))
288 .add(r11Vec.mul((r20Vec.mul(qxy).add(r21Vec.mul(qyy)).add(r22Vec.mul(qyz)))))
289 .add(r12Vec.mul((r20Vec.mul(qxz).add(r21Vec.mul(qyz)).add(r22Vec.mul(qzz)))));
290 m.qyz = m.qyz.mul(2.0);
291
292 m.qzz = r20Vec.mul(r20Vec.mul(qxx).add(r21Vec.mul(qxy)).add(r22Vec.mul(qxz)))
293 .add(r21Vec.mul((r20Vec.mul(qxy).add(r21Vec.mul(qyy)).add(r22Vec.mul(qyz)))))
294 .add(r22Vec.mul((r20Vec.mul(qxz).add(r21Vec.mul(qyz)).add(r22Vec.mul(qzz)))));
295
296 }
297
298
299
300
301
302
303 public void rotateInducedDipoles(PolarizableMultipoleSIMD m) {
304 DoubleVector dx = m.ux;
305 DoubleVector dy = m.uy;
306 DoubleVector dz = m.uz;
307 m.ux = r00Vec.mul(dx).add(r01Vec.mul(dy)).add(r02Vec.mul(dz));
308 m.uy = r10Vec.mul(dx).add(r11Vec.mul(dy)).add(r12Vec.mul(dz));
309 m.uz = r20Vec.mul(dx).add(r21Vec.mul(dy)).add(r22Vec.mul(dz));
310 dx = m.px;
311 dy = m.py;
312 dz = m.pz;
313 m.px = r00Vec.mul(dx).add(r01Vec.mul(dy)).add(r02Vec.mul(dz));
314 m.py = r10Vec.mul(dx).add(r11Vec.mul(dy)).add(r12Vec.mul(dz));
315 m.pz = r20Vec.mul(dx).add(r21Vec.mul(dy)).add(r22Vec.mul(dz));
316
317 m.sx = m.ux.add(m.px).mul(0.5);
318 m.sy = m.uy.add(m.py).mul(0.5);
319 m.sz = m.uz.add(m.pz).mul(0.5);
320 }
321
322
323
324
325
326
327 public void toGlobal(DoubleVector[] v) {
328 DoubleVector vx = v[0];
329 DoubleVector vy = v[1];
330 DoubleVector vz = v[2];
331
332 v[0] = ir00Vec.mul(vx).add(ir01Vec.mul(vy)).add(ir02Vec.mul(vz));
333
334 v[1] = ir10Vec.mul(vx).add(ir11Vec.mul(vy)).add(ir12Vec.mul(vz));
335
336 v[2] = ir20Vec.mul(vx).add(ir21Vec.mul(vy)).add(ir22Vec.mul(vz));
337 }
338 }