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
42
43
44
45
46
47
48
49 public class GKTensorGlobal extends CoulombTensorGlobal {
50
51
52
53
54 protected final GKMultipoleOrder multipoleOrder;
55
56
57
58
59 private final double c;
60
61 private final GKSource gkSource;
62
63
64
65
66
67
68
69
70
71
72 public GKTensorGlobal(GKMultipoleOrder multipoleOrder, int order, GKSource gkSource,
73 double Eh, double Es) {
74 super(order);
75 this.multipoleOrder = multipoleOrder;
76 this.gkSource = gkSource;
77
78
79 c = GKSource.cn(multipoleOrder.getOrder(), Eh, Es);
80 }
81
82
83
84
85
86
87
88
89 @Override
90 public double multipoleEnergy(PolarizableMultipole mI, PolarizableMultipole mK) {
91 return switch (multipoleOrder) {
92 default -> {
93 chargeIPotentialAtK(mI, 2);
94 double eK = multipoleEnergy(mK);
95 chargeKPotentialAtI(mK, 2);
96 double eI = multipoleEnergy(mI);
97 yield c * 0.5 * (eK + eI);
98 }
99 case DIPOLE -> {
100 dipoleIPotentialAtK(mI.dx, mI.dy, mI.dz, 2);
101 double eK = multipoleEnergy(mK);
102 dipoleKPotentialAtI(mK.dx, mK.dy, mK.dz, 2);
103 double eI = multipoleEnergy(mI);
104 yield c * 0.5 * (eK + eI);
105 }
106 case QUADRUPOLE -> {
107 quadrupoleIPotentialAtK(mI, 2);
108 double eK = multipoleEnergy(mK);
109 quadrupoleKPotentialAtI(mK, 2);
110 double eI = multipoleEnergy(mI);
111 yield c * 0.5 * (eK + eI);
112 }
113 };
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127 @Override
128 public double multipoleEnergyAndGradient(PolarizableMultipole mI, PolarizableMultipole mK,
129 double[] Gi, double[] Gk, double[] Ti, double[] Tk) {
130 return switch (multipoleOrder) {
131 default -> monopoleEnergyAndGradient(mI, mK, Gi, Gk, Ti, Tk);
132 case DIPOLE -> dipoleEnergyAndGradient(mI, mK, Gi, Gk, Ti, Tk);
133 case QUADRUPOLE -> quadrupoleEnergyAndGradient(mI, mK, Gi, Gk, Ti, Tk);
134 };
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148 protected double monopoleEnergyAndGradient(PolarizableMultipole mI, PolarizableMultipole mK,
149 double[] Gi, double[] Gk, double[] Ti, double[] Tk) {
150
151
152 chargeIPotentialAtK(mI, 3);
153 double eK = multipoleEnergy(mK);
154 multipoleGradient(mK, Gk);
155 multipoleTorque(mK, Tk);
156
157
158 chargeKPotentialAtI(mK, 3);
159 double eI = multipoleEnergy(mI);
160 multipoleGradient(mI, Gi);
161 multipoleTorque(mI, Ti);
162
163 double scale = c * 0.5;
164 Gi[0] = scale * (Gi[0] - Gk[0]);
165 Gi[1] = scale * (Gi[1] - Gk[1]);
166 Gi[2] = scale * (Gi[2] - Gk[2]);
167 Gk[0] = -Gi[0];
168 Gk[1] = -Gi[1];
169 Gk[2] = -Gi[2];
170
171 Ti[0] = scale * Ti[0];
172 Ti[1] = scale * Ti[1];
173 Ti[2] = scale * Ti[2];
174 Tk[0] = scale * Tk[0];
175 Tk[1] = scale * Tk[1];
176 Tk[2] = scale * Tk[2];
177
178 return scale * (eK + eI);
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192 protected double dipoleEnergyAndGradient(PolarizableMultipole mI, PolarizableMultipole mK,
193 double[] Gi, double[] Gk, double[] Ti, double[] Tk) {
194
195
196 dipoleIPotentialAtK(mI.dx, mI.dy, mI.dz, 3);
197 double eK = multipoleEnergy(mK);
198 multipoleGradient(mK, Gk);
199 multipoleTorque(mK, Tk);
200
201
202
203 multipoleKPotentialAtI(mK, 1);
204 dipoleTorque(mI, Ti);
205
206
207 dipoleKPotentialAtI(mK.dx, mK.dy, mK.dz, 3);
208 double eI = multipoleEnergy(mI);
209 multipoleGradient(mI, Gi);
210 multipoleTorque(mI, Ti);
211
212
213
214 multipoleIPotentialAtK(mI, 1);
215 dipoleTorque(mK, Tk);
216
217 double scale = c * 0.5;
218 Gi[0] = scale * (Gi[0] - Gk[0]);
219 Gi[1] = scale * (Gi[1] - Gk[1]);
220 Gi[2] = scale * (Gi[2] - Gk[2]);
221 Gk[0] = -Gi[0];
222 Gk[1] = -Gi[1];
223 Gk[2] = -Gi[2];
224
225 Ti[0] = scale * Ti[0];
226 Ti[1] = scale * Ti[1];
227 Ti[2] = scale * Ti[2];
228 Tk[0] = scale * Tk[0];
229 Tk[1] = scale * Tk[1];
230 Tk[2] = scale * Tk[2];
231
232 return scale * (eK + eI);
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246 protected double quadrupoleEnergyAndGradient(PolarizableMultipole mI, PolarizableMultipole mK,
247 double[] Gi, double[] Gk, double[] Ti, double[] Tk) {
248
249
250 quadrupoleIPotentialAtK(mI, 3);
251 double eK = multipoleEnergy(mK);
252 multipoleGradient(mK, Gk);
253 multipoleTorque(mK, Tk);
254
255
256 multipoleKPotentialAtI(mK, 2);
257 quadrupoleTorque(mI, Ti);
258
259
260 quadrupoleKPotentialAtI(mK, 3);
261 double eI = multipoleEnergy(mI);
262 multipoleGradient(mI, Gi);
263 multipoleTorque(mI, Ti);
264
265
266 multipoleIPotentialAtK(mI, 2);
267 quadrupoleTorque(mK, Tk);
268
269 double scale = c * 0.5;
270 Gi[0] = scale * (Gi[0] - Gk[0]);
271 Gi[1] = scale * (Gi[1] - Gk[1]);
272 Gi[2] = scale * (Gi[2] - Gk[2]);
273 Gk[0] = -Gi[0];
274 Gk[1] = -Gi[1];
275 Gk[2] = -Gi[2];
276
277 Ti[0] = scale * Ti[0];
278 Ti[1] = scale * Ti[1];
279 Ti[2] = scale * Ti[2];
280 Tk[0] = scale * Tk[0];
281 Tk[1] = scale * Tk[1];
282 Tk[2] = scale * Tk[2];
283
284 return scale * (eK + eI);
285 }
286
287
288
289
290
291
292
293
294 public double multipoleEnergyBornGrad(PolarizableMultipole mI, PolarizableMultipole mK) {
295 return multipoleEnergy(mI, mK);
296 }
297
298
299
300
301
302
303
304
305
306
307 public double polarizationEnergy(PolarizableMultipole mI, PolarizableMultipole mK, DoubleVector scaleEnergy) {
308 return polarizationEnergy(mI, mK);
309 }
310
311
312
313
314
315
316
317
318 public double polarizationEnergy(PolarizableMultipole mI, PolarizableMultipole mK) {
319 return switch (multipoleOrder) {
320 default -> {
321
322 chargeIPotentialAtK(mI, 1);
323
324 double eK = polarizationEnergy(mK);
325
326 chargeKPotentialAtI(mK, 1);
327
328 double eI = polarizationEnergy(mI);
329 yield c * 0.5 * (eK + eI);
330 }
331 case DIPOLE -> {
332
333 dipoleIPotentialAtK(mI.dx, mI.dy, mI.dz, 1);
334
335 double eK = polarizationEnergy(mK);
336
337 dipoleIPotentialAtK(mI.ux, mI.uy, mI.uz, 2);
338
339 eK += 0.5 * multipoleEnergy(mK);
340
341 dipoleKPotentialAtI(mK.dx, mK.dy, mK.dz, 1);
342
343 double eI = polarizationEnergy(mI);
344
345 dipoleKPotentialAtI(mK.ux, mK.uy, mK.uz, 2);
346
347 eI += 0.5 * multipoleEnergy(mI);
348 yield c * 0.5 * (eK + eI);
349 }
350 case QUADRUPOLE -> {
351
352 quadrupoleIPotentialAtK(mI, 1);
353
354 double eK = polarizationEnergy(mK);
355
356 quadrupoleKPotentialAtI(mK, 1);
357
358 double eI = polarizationEnergy(mI);
359 yield c * 0.5 * (eK + eI);
360 }
361 };
362 }
363
364
365
366
367
368
369
370
371 public double polarizationEnergyBorn(PolarizableMultipole mI, PolarizableMultipole mK) {
372 return switch (multipoleOrder) {
373 default -> {
374
375 chargeIPotentialAtK(mI, 1);
376
377 double eK = polarizationEnergyS(mK);
378
379 chargeKPotentialAtI(mK, 1);
380
381 double eI = polarizationEnergyS(mI);
382 yield c * 0.5 * (eK + eI);
383 }
384 case DIPOLE -> {
385
386 dipoleIPotentialAtK(mI.dx, mI.dy, mI.dz, 1);
387
388 double eK = polarizationEnergyS(mK);
389
390 dipoleIPotentialAtK(mI.sx, mI.sy, mI.sz, 2);
391
392 eK += 0.5 * multipoleEnergy(mK);
393
394 dipoleKPotentialAtI(mK.dx, mK.dy, mK.dz, 1);
395
396 double eI = polarizationEnergyS(mI);
397
398 dipoleKPotentialAtI(mK.sx, mK.sy, mK.sz, 2);
399
400 eI += 0.5 * multipoleEnergy(mI);
401 yield c * 0.5 * (eK + eI);
402 }
403 case QUADRUPOLE -> {
404
405 quadrupoleIPotentialAtK(mI, 1);
406
407 double eK = polarizationEnergyS(mK);
408
409 quadrupoleKPotentialAtI(mK, 1);
410
411 double eI = polarizationEnergyS(mI);
412 yield c * 0.5 * (eK + eI);
413 }
414 };
415 }
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432 @Override
433 public double polarizationEnergyAndGradient(PolarizableMultipole mI, PolarizableMultipole mK,
434 double inductionMask, double energyMask, double mutualMask, double[] Gi, double[] Ti,
435 double[] Tk) {
436 return switch (multipoleOrder) {
437 default -> monopolePolarizationEnergyAndGradient(mI, mK, Gi);
438 case DIPOLE -> dipolePolarizationEnergyAndGradient(mI, mK, mutualMask, Gi, Ti, Tk);
439 case QUADRUPOLE -> quadrupolePolarizationEnergyAndGradient(mI, mK, Gi, Ti, Tk);
440 };
441 }
442
443
444
445
446
447
448
449
450
451 public double monopolePolarizationEnergyAndGradient(PolarizableMultipole mI,
452 PolarizableMultipole mK, double[] Gi) {
453
454
455 chargeIPotentialAtK(mI, 2);
456
457 double eK = polarizationEnergy(mK);
458
459 Gi[0] = -(mK.sx * E200 + mK.sy * E110 + mK.sz * E101);
460 Gi[1] = -(mK.sx * E110 + mK.sy * E020 + mK.sz * E011);
461 Gi[2] = -(mK.sx * E101 + mK.sy * E011 + mK.sz * E002);
462
463
464 chargeKPotentialAtI(mK, 2);
465
466 double eI = polarizationEnergy(mI);
467
468 Gi[0] += (mI.sx * E200 + mI.sy * E110 + mI.sz * E101);
469 Gi[1] += (mI.sx * E110 + mI.sy * E020 + mI.sz * E011);
470 Gi[2] += (mI.sx * E101 + mI.sy * E011 + mI.sz * E002);
471
472 double scale = c * 0.5;
473 Gi[0] *= scale;
474 Gi[1] *= scale;
475 Gi[2] *= scale;
476
477
478 return scale * (eI + eK);
479 }
480
481
482
483
484
485
486
487
488
489
490
491
492 public double dipolePolarizationEnergyAndGradient(PolarizableMultipole mI, PolarizableMultipole mK,
493 double mutualMask, double[] Gi, double[] Ti, double[] Tk) {
494
495
496 dipoleIPotentialAtK(mI.dx, mI.dy, mI.dz, 2);
497
498 double eK = polarizationEnergy(mK);
499
500 Gi[0] = -(mK.sx * E200 + mK.sy * E110 + mK.sz * E101);
501 Gi[1] = -(mK.sx * E110 + mK.sy * E020 + mK.sz * E011);
502 Gi[2] = -(mK.sx * E101 + mK.sy * E011 + mK.sz * E002);
503
504 dipoleIPotentialAtK(mI.sx, mI.sy, mI.sz, 2);
505 dipoleTorque(mK, Tk);
506
507
508 dipoleIPotentialAtK(mI.ux, mI.uy, mI.uz, 3);
509
510 eK += 0.5 * multipoleEnergy(mK);
511 double[] G = new double[3];
512 multipoleGradient(mK, G);
513 Gi[0] -= G[0];
514 Gi[1] -= G[1];
515 Gi[2] -= G[2];
516 multipoleTorque(mK, Tk);
517
518
519 dipoleKPotentialAtI(mK.dx, mK.dy, mK.dz, 2);
520
521 double eI = polarizationEnergy(mI);
522
523 Gi[0] += (mI.sx * E200 + mI.sy * E110 + mI.sz * E101);
524 Gi[1] += (mI.sx * E110 + mI.sy * E020 + mI.sz * E011);
525 Gi[2] += (mI.sx * E101 + mI.sy * E011 + mI.sz * E002);
526
527 dipoleKPotentialAtI(mK.sx, mK.sy, mK.sz, 2);
528 dipoleTorque(mI, Ti);
529
530
531 dipoleKPotentialAtI(mK.ux, mK.uy, mK.uz, 3);
532
533 eI += 0.5 * multipoleEnergy(mI);
534 G = new double[3];
535 multipoleGradient(mI, G);
536 Gi[0] += G[0];
537 Gi[1] += G[1];
538 Gi[2] += G[2];
539 multipoleTorque(mI, Ti);
540
541
542
543 if (mutualMask != 0.0) {
544
545 dipoleIPotentialAtK(mI.ux, mI.uy, mI.uz, 2);
546 Gi[0] -= mutualMask * (mK.px * E200 + mK.py * E110 + mK.pz * E101);
547 Gi[1] -= mutualMask * (mK.px * E110 + mK.py * E020 + mK.pz * E011);
548 Gi[2] -= mutualMask * (mK.px * E101 + mK.py * E011 + mK.pz * E002);
549
550
551 dipoleKPotentialAtI(mK.ux, mK.uy, mK.uz, 2);
552 Gi[0] += mutualMask * (mI.px * E200 + mI.py * E110 + mI.pz * E101);
553 Gi[1] += mutualMask * (mI.px * E110 + mI.py * E020 + mI.pz * E011);
554 Gi[2] += mutualMask * (mI.px * E101 + mI.py * E011 + mI.pz * E002);
555 }
556
557
558 double scale = c * 0.5;
559 double energy = scale * (eI + eK);
560 Gi[0] *= scale;
561 Gi[1] *= scale;
562 Gi[2] *= scale;
563 Ti[0] *= scale;
564 Ti[1] *= scale;
565 Ti[2] *= scale;
566 Tk[0] *= scale;
567 Tk[1] *= scale;
568 Tk[2] *= scale;
569
570 return energy;
571 }
572
573
574
575
576
577
578
579
580
581
582
583 public double quadrupolePolarizationEnergyAndGradient(PolarizableMultipole mI, PolarizableMultipole mK,
584 double[] Gi, double[] Ti, double[] Tk) {
585
586
587 quadrupoleIPotentialAtK(mI, 2);
588
589 double eK = polarizationEnergy(mK);
590
591 Gi[0] = -(mK.sx * E200 + mK.sy * E110 + mK.sz * E101);
592 Gi[1] = -(mK.sx * E110 + mK.sy * E020 + mK.sz * E011);
593 Gi[2] = -(mK.sx * E101 + mK.sy * E011 + mK.sz * E002);
594
595
596 quadrupoleKPotentialAtI(mK, 2);
597
598 double eI = polarizationEnergy(mI);
599
600 Gi[0] += (mI.sx * E200 + mI.sy * E110 + mI.sz * E101);
601 Gi[1] += (mI.sx * E110 + mI.sy * E020 + mI.sz * E011);
602 Gi[2] += (mI.sx * E101 + mI.sy * E011 + mI.sz * E002);
603
604 double scale = c * 0.5;
605 Gi[0] *= scale;
606 Gi[1] *= scale;
607 Gi[2] *= scale;
608
609
610 dipoleIPotentialAtK(scale * mI.sx, scale * mI.sy, scale * mI.sz, 2);
611 quadrupoleTorque(mK, Tk);
612
613
614 dipoleKPotentialAtI(scale * mK.sx, scale * mK.sy, scale * mK.sz, 2);
615 quadrupoleTorque(mI, Ti);
616
617
618 return scale * (eI + eK);
619 }
620
621
622
623
624
625
626
627
628 public double polarizationEnergyBornGrad(PolarizableMultipole mI, PolarizableMultipole mK) {
629 return 2.0 * polarizationEnergyBorn(mI, mK);
630 }
631
632
633
634
635
636
637
638
639 public double mutualPolarizationEnergyBornGrad(PolarizableMultipole mI, PolarizableMultipole mK) {
640 double db = 0.0;
641 if (multipoleOrder == GKMultipoleOrder.DIPOLE) {
642
643 dipoleIPotentialAtK(mI.ux, mI.uy, mI.uz, 2);
644 db = 0.5 * (mK.px * E100 + mK.py * E010 + mK.pz * E001);
645
646
647 dipoleKPotentialAtI(mK.ux, mK.uy, mK.uz, 2);
648 db += 0.5 * (mI.px * E100 + mI.py * E010 + mI.pz * E001);
649 }
650 return c * db;
651 }
652
653
654
655
656 @Override
657 protected void source(double[] work) {
658 gkSource.source(work, multipoleOrder);
659 }
660
661 }