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.potential.nonbonded.pme;
39
40 import edu.rit.pj.IntegerForLoop;
41 import edu.rit.pj.IntegerSchedule;
42 import edu.rit.pj.ParallelRegion;
43 import edu.rit.pj.ParallelTeam;
44 import edu.rit.pj.reduction.SharedDouble;
45 import edu.rit.pj.reduction.SharedInteger;
46 import ffx.crystal.Crystal;
47 import ffx.crystal.SymOp;
48 import ffx.numerics.atomic.AtomicDoubleArray3D;
49 import ffx.potential.bonded.Atom;
50 import ffx.potential.extended.ExtendedSystem;
51 import ffx.potential.nonbonded.MaskingInterface;
52 import ffx.potential.parameters.ForceField;
53 import ffx.potential.parameters.MultipoleType.MultipoleFrameDefinition;
54 import ffx.potential.utils.EnergyException;
55
56 import java.util.List;
57 import java.util.logging.Level;
58 import java.util.logging.Logger;
59
60 import static ffx.numerics.special.Erf.erfc;
61 import static ffx.potential.parameters.MultipoleType.t000;
62 import static ffx.potential.parameters.MultipoleType.t001;
63 import static ffx.potential.parameters.MultipoleType.t002;
64 import static ffx.potential.parameters.MultipoleType.t010;
65 import static ffx.potential.parameters.MultipoleType.t011;
66 import static ffx.potential.parameters.MultipoleType.t020;
67 import static ffx.potential.parameters.MultipoleType.t100;
68 import static ffx.potential.parameters.MultipoleType.t101;
69 import static ffx.potential.parameters.MultipoleType.t110;
70 import static ffx.potential.parameters.MultipoleType.t200;
71 import static java.lang.Double.isInfinite;
72 import static java.lang.Double.isNaN;
73 import static java.lang.String.format;
74 import static java.util.Arrays.fill;
75 import static org.apache.commons.math3.util.FastMath.exp;
76 import static org.apache.commons.math3.util.FastMath.min;
77 import static org.apache.commons.math3.util.FastMath.sqrt;
78
79
80
81
82
83
84
85 public class RealSpaceEnergyRegion extends ParallelRegion implements MaskingInterface {
86 private static final Logger logger = Logger.getLogger(RealSpaceEnergyRegion.class.getName());
87
88
89
90 private static final double oneThird = 1.0 / 3.0;
91 private final int maxThreads;
92 private final double electric;
93 private final SharedInteger sharedInteractions;
94 private final ForceField.ELEC_FORM elecForm;
95 private final RealSpaceEnergyLoop[] realSpaceEnergyLoop;
96 private final FixedChargeEnergyLoop[] fixedChargeEnergyLoop;
97
98
99
100 private final boolean intermolecularSoftcore;
101
102
103
104 private final boolean intramolecularSoftcore;
105
106
107
108 public double[][][] inducedDipole;
109 public double[][][] inducedDipoleCR;
110
111
112
113 protected int[][] ip11;
114
115
116
117 private Atom[] atoms;
118
119
120
121 private Crystal crystal;
122
123
124
125 private double[][][] coordinates;
126
127
128
129 private MultipoleFrameDefinition[] frame;
130
131
132
133 private int[][] axisAtom;
134
135
136
137 private double[][][] globalMultipole;
138 private double[][][] titrationMultipole;
139 private double[][][] tautomerMultipole;
140
141 private ExtendedSystem extendedSystem = null;
142 private boolean esvTerm = false;
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161 private boolean[] use;
162
163
164
165 private int[] molecule;
166
167
168
169 private boolean[] isSoft;
170 private double[] ipdamp;
171 private double[] thole;
172
173
174
175 private int[][] mask12;
176 private int[][] mask13;
177 private int[][] mask14;
178 private int[][] mask15;
179
180
181
182 private int[][][] realSpaceLists;
183
184
185
186 private int[][] realSpaceCounts;
187
188
189
190 private IntegerSchedule realSpaceSchedule;
191 private long[] realSpaceEnergyTime;
192
193
194
195 private AtomicDoubleArray3D grad;
196
197
198
199 private AtomicDoubleArray3D torque;
200
201
202
203 private AtomicDoubleArray3D lambdaGrad;
204
205
206
207 private AtomicDoubleArray3D lambdaTorque;
208
209
210
211 private SharedDouble shareddEdLambda;
212
213
214
215 private SharedDouble sharedd2EdLambda2;
216
217
218
219 private boolean gradient;
220
221
222
223
224 private boolean lambdaTerm;
225
226
227
228 private boolean nnTerm;
229
230
231
232
233 private LambdaMode lambdaMode = LambdaMode.OFF;
234 private Polarization polarization;
235
236
237
238 private double lAlpha = 0.0;
239 private double dlAlpha = 0.0;
240 private double d2lAlpha = 0.0;
241 private double dEdLSign = 1.0;
242
243
244
245 private double dlPowPerm = 0.0;
246 private double d2lPowPerm = 0.0;
247 private boolean doPermanentRealSpace;
248 private double permanentScale = 1.0;
249
250
251
252 private double lPowPol = 1.0;
253 private double dlPowPol = 0.0;
254 private double d2lPowPol = 0.0;
255 private boolean doPolarization;
256
257
258
259
260
261
262
263
264
265
266
267
268
269 private double polarizationScale = 1.0;
270
271
272
273 private double aewald;
274 private double an0;
275 private double an1;
276 private double an2;
277 private double an3;
278 private double an4;
279 private double an5;
280 private double permanentEnergy;
281 private double polarizationEnergy;
282 private ScaleParameters scaleParameters;
283
284 public RealSpaceEnergyRegion(ForceField.ELEC_FORM elecForm, int nt, ForceField forceField, boolean lambdaTerm, double electric) {
285 maxThreads = nt;
286 this.electric = electric;
287 this.elecForm = elecForm;
288 sharedInteractions = new SharedInteger();
289 if (elecForm == ForceField.ELEC_FORM.FIXED_CHARGE) {
290 fixedChargeEnergyLoop = new FixedChargeEnergyLoop[nt];
291 realSpaceEnergyLoop = null;
292 } else {
293 fixedChargeEnergyLoop = null;
294 realSpaceEnergyLoop = new RealSpaceEnergyLoop[nt];
295 }
296
297
298 if (lambdaTerm) {
299 intermolecularSoftcore = forceField.getBoolean("INTERMOLECULAR_SOFTCORE", false);
300 intramolecularSoftcore = forceField.getBoolean("INTRAMOLECULAR_SOFTCORE", false);
301 } else {
302 intermolecularSoftcore = false;
303 intramolecularSoftcore = false;
304 }
305 }
306
307 @Override
308 public void applyMask(int i, boolean[] is14, double[]... masks) {
309 if (ip11[i] != null) {
310
311 double[] permanentEnergyMask = masks[0];
312 double[] permanentFieldMask = masks[1];
313 for (int value : mask12[i]) {
314 permanentFieldMask[value] = scaleParameters.p12scale;
315 permanentEnergyMask[value] = scaleParameters.m12scale;
316 }
317 for (int value : mask13[i]) {
318 permanentFieldMask[value] = scaleParameters.p13scale;
319 permanentEnergyMask[value] = scaleParameters.m13scale;
320 }
321 for (int value : mask14[i]) {
322 permanentFieldMask[value] = scaleParameters.p14scale;
323 permanentEnergyMask[value] = scaleParameters.m14scale;
324 for (int k : ip11[i]) {
325 if (k == value) {
326 permanentFieldMask[value] = scaleParameters.intra14Scale * scaleParameters.p14scale;
327 break;
328 }
329 }
330 }
331 for (int value : mask15[i]) {
332 permanentEnergyMask[value] = scaleParameters.m15scale;
333 }
334
335 double[] polarizationGroupMask = masks[2];
336 for (int j : ip11[i]) {
337 polarizationGroupMask[j] = scaleParameters.d11scale;
338 }
339 } else {
340
341 double[] permanentEnergyMask = masks[0];
342 for (int value : mask12[i]) {
343 permanentEnergyMask[value] = scaleParameters.m12scale;
344 }
345 for (int value : mask13[i]) {
346 permanentEnergyMask[value] = scaleParameters.m13scale;
347 }
348 for (int value : mask14[i]) {
349 permanentEnergyMask[value] = scaleParameters.m14scale;
350 }
351 }
352 }
353
354
355
356
357
358
359 public void executeWith(ParallelTeam parallelTeam) {
360 try {
361 parallelTeam.execute(this);
362 } catch (Exception e) {
363 String message = " Exception computing the electrostatic energy.\n";
364 logger.log(Level.SEVERE, message, e);
365 }
366 }
367
368 @Override
369 public void finish() {
370 permanentEnergy = 0.0;
371 polarizationEnergy = 0.0;
372 if (elecForm == ForceField.ELEC_FORM.FIXED_CHARGE) {
373 for (int i = 0; i < maxThreads; i++) {
374 permanentEnergy += fixedChargeEnergyLoop[i].permanentEnergy;
375 }
376 } else {
377 for (int i = 0; i < maxThreads; i++) {
378 permanentEnergy += realSpaceEnergyLoop[i].permanentEnergy;
379 polarizationEnergy += realSpaceEnergyLoop[i].inducedEnergy;
380 }
381 }
382 permanentEnergy *= electric;
383 polarizationEnergy *= electric;
384 if (isNaN(permanentEnergy)) {
385 throw new EnergyException(
386 format(" The permanent multipole energy is %16.8f", permanentEnergy));
387 }
388 if (isNaN(polarizationEnergy)) {
389 throw new EnergyException(
390 format(" The polarization energy is %16.8f", polarizationEnergy));
391 }
392 }
393
394 public int getCount(int i) {
395 if (elecForm == ForceField.ELEC_FORM.FIXED_CHARGE) {
396 return fixedChargeEnergyLoop[i].getCount();
397 } else {
398 return realSpaceEnergyLoop[i].getCount();
399 }
400 }
401
402 public int getInteractions() {
403 return sharedInteractions.get();
404 }
405
406 public double getPermanentEnergy() {
407 return permanentEnergy;
408 }
409
410 public double getPolarizationEnergy() {
411 return polarizationEnergy;
412 }
413
414 public void init(
415 Atom[] atoms,
416 Crystal crystal,
417 ExtendedSystem extendedSystem,
418 boolean esvTerm,
419 double[][][] coordinates,
420 MultipoleFrameDefinition[] frame,
421 int[][] axisAtom,
422 double[][][] globalMultipole,
423 double[][][] titrationMultipole,
424 double[][][] tautomerMultipole,
425 double[][][] inducedDipole,
426 double[][][] inducedDipoleCR,
427 boolean[] use,
428 int[] molecule,
429 int[][] ip11,
430 int[][] mask12,
431 int[][] mask13,
432 int[][] mask14,
433 int[][] mask15,
434 boolean[] isSoft,
435 double[] ipdamp,
436 double[] thole,
437 RealSpaceNeighborParameters realSpaceNeighborParameters,
438 boolean gradient,
439 boolean lambdaTerm,
440 boolean nnTerm,
441 LambdaMode lambdaMode,
442 Polarization polarization,
443 EwaldParameters ewaldParameters,
444 ScaleParameters scaleParameters,
445 AlchemicalParameters alchemicalParameters,
446 long[] realSpaceEnergyTime,
447 AtomicDoubleArray3D grad,
448 AtomicDoubleArray3D torque,
449 AtomicDoubleArray3D lambdaGrad,
450 AtomicDoubleArray3D lambdaTorque,
451 SharedDouble shareddEdLambda,
452 SharedDouble sharedd2EdLambda2) {
453
454 this.atoms = atoms;
455 this.crystal = crystal;
456 this.extendedSystem = extendedSystem;
457 this.esvTerm = esvTerm;
458 this.coordinates = coordinates;
459 this.frame = frame;
460 this.axisAtom = axisAtom;
461 this.globalMultipole = globalMultipole;
462 this.titrationMultipole = titrationMultipole;
463 this.tautomerMultipole = tautomerMultipole;
464 this.inducedDipole = inducedDipole;
465 this.inducedDipoleCR = inducedDipoleCR;
466 this.use = use;
467 this.molecule = molecule;
468 this.ip11 = ip11;
469 this.mask12 = mask12;
470 this.mask13 = mask13;
471 this.mask14 = mask14;
472 this.mask15 = mask15;
473 this.isSoft = isSoft;
474 this.ipdamp = ipdamp;
475 this.thole = thole;
476 this.realSpaceLists = realSpaceNeighborParameters.realSpaceLists;
477 this.realSpaceCounts = realSpaceNeighborParameters.realSpaceCounts;
478 this.realSpaceSchedule = realSpaceNeighborParameters.realSpaceSchedule;
479 this.gradient = gradient;
480 this.lambdaTerm = lambdaTerm;
481 this.nnTerm = nnTerm;
482 this.lambdaMode = lambdaMode;
483 this.polarization = polarization;
484 this.lAlpha = alchemicalParameters.lAlpha;
485 this.dlAlpha = alchemicalParameters.dlAlpha;
486 this.d2lAlpha = alchemicalParameters.d2lAlpha;
487 this.dEdLSign = alchemicalParameters.dEdLSign;
488 this.dlPowPerm = alchemicalParameters.dlPowPerm;
489 this.d2lPowPerm = alchemicalParameters.d2lPowPerm;
490 this.doPermanentRealSpace = alchemicalParameters.doPermanentRealSpace;
491 this.permanentScale = alchemicalParameters.permanentScale;
492 this.lPowPol = alchemicalParameters.lPowPol;
493 this.dlPowPol = alchemicalParameters.dlPowPol;
494 this.d2lPowPol = alchemicalParameters.d2lPowPol;
495 this.doPolarization = alchemicalParameters.doPolarization;
496 this.polarizationScale = alchemicalParameters.polarizationScale;
497 this.aewald = ewaldParameters.aewald;
498 this.an0 = ewaldParameters.an0;
499 this.an1 = ewaldParameters.an1;
500 this.an2 = ewaldParameters.an2;
501 this.an3 = ewaldParameters.an3;
502 this.an4 = ewaldParameters.an4;
503 this.an5 = ewaldParameters.an5;
504 this.scaleParameters = scaleParameters;
505
506 this.realSpaceEnergyTime = realSpaceEnergyTime;
507 this.grad = grad;
508 this.torque = torque;
509 this.lambdaGrad = lambdaGrad;
510 this.lambdaTorque = lambdaTorque;
511 this.shareddEdLambda = shareddEdLambda;
512 this.sharedd2EdLambda2 = sharedd2EdLambda2;
513 }
514
515 @Override
516 public void removeMask(int i, boolean[] is14, double[]... masks) {
517 if (ip11[i] != null) {
518
519 double[] permanentEnergyMask = masks[0];
520 double[] permanentFieldMask = masks[1];
521 for (int value : mask12[i]) {
522 permanentFieldMask[value] = 1.0;
523 permanentEnergyMask[value] = 1.0;
524 }
525 for (int value : mask13[i]) {
526 permanentFieldMask[value] = 1.0;
527 permanentEnergyMask[value] = 1.0;
528 }
529 for (int value : mask14[i]) {
530 permanentFieldMask[value] = 1.0;
531 permanentEnergyMask[value] = 1.0;
532 for (int k : ip11[i]) {
533 if (k == value) {
534 permanentFieldMask[value] = 1.0;
535 break;
536 }
537 }
538 }
539 for (int value : mask15[i]) {
540 permanentEnergyMask[value] = 1.0;
541 }
542
543 double[] polarizationGroupMask = masks[2];
544 for (int j : ip11[i]) {
545 polarizationGroupMask[j] = 1.0;
546 }
547 } else {
548
549 double[] permanentEnergyMask = masks[0];
550 for (int value : mask12[i]) {
551 permanentEnergyMask[value] = 1.0;
552 }
553 for (int value : mask13[i]) {
554 permanentEnergyMask[value] = 1.0;
555 }
556 for (int value : mask14[i]) {
557 permanentEnergyMask[value] = 1.0;
558 }
559 }
560 }
561
562 @Override
563 public void run() {
564 int threadIndex = getThreadIndex();
565 if (elecForm == ForceField.ELEC_FORM.FIXED_CHARGE) {
566 if (fixedChargeEnergyLoop[threadIndex] == null) {
567 fixedChargeEnergyLoop[threadIndex] = new FixedChargeEnergyLoop();
568 }
569 try {
570 int nAtoms = atoms.length;
571 execute(0, nAtoms - 1, fixedChargeEnergyLoop[threadIndex]);
572 } catch (Exception e) {
573 String message =
574 "Fatal exception computing the real space energy in thread " + getThreadIndex() + "\n";
575 logger.log(Level.SEVERE, message, e);
576 }
577 } else {
578 if (realSpaceEnergyLoop[threadIndex] == null) {
579 realSpaceEnergyLoop[threadIndex] = new RealSpaceEnergyLoop();
580 }
581 try {
582 int nAtoms = atoms.length;
583 execute(0, nAtoms - 1, realSpaceEnergyLoop[threadIndex]);
584 } catch (Exception e) {
585 String message =
586 "Fatal exception computing the real space energy in thread " + getThreadIndex() + "\n";
587 logger.log(Level.SEVERE, message, e);
588 }
589 }
590 }
591
592 @Override
593 public void start() {
594 sharedInteractions.set(0);
595 }
596
597
598
599
600
601
602
603
604
605
606 private void log(int i, int k, double r, double eij, int count, double total) {
607 logger.info(format("%s %6d %6d %12.10f %12.10f %8d %16.10f",
608 "ELEC", atoms[i].getIndex(), atoms[k].getIndex(), r, eij, count, total));
609 }
610
611
612
613
614
615 private class RealSpaceEnergyLoop extends IntegerForLoop {
616
617 private final double[] dx_local;
618 private final double[][] rot_local;
619 private final Torque torques;
620 private double ci;
621 private double dix, diy, diz;
622 private double qixx, qiyy, qizz, qixy, qixz, qiyz;
623 private double ck;
624 private double dkx, dky, dkz;
625 private double qkxx, qkyy, qkzz, qkxy, qkxz, qkyz;
626 private double uix, uiy, uiz;
627 private double pix, piy, piz;
628 private double xr, yr, zr;
629 private double ukx, uky, ukz;
630 private double pkx, pky, pkz;
631 private double bn0, bn1, bn2, bn3, bn4, bn5, bn6;
632 private double rr1, rr3, rr5, rr7, rr9, rr11, rr13;
633 private double scale, scale3, scale5, scale7;
634 private double scalep, scaled;
635 private double ddsc3x, ddsc3y, ddsc3z;
636 private double ddsc5x, ddsc5y, ddsc5z;
637 private double ddsc7x, ddsc7y, ddsc7z;
638 private double l2;
639 private boolean soft;
640 private double selfScale;
641 private double permanentEnergy;
642 private double inducedEnergy;
643 private double dUdL, d2UdL2;
644 private int i, k, iSymm, count;
645 private double[] gxk_local, gyk_local, gzk_local;
646 private double[] txk_local, tyk_local, tzk_local;
647 private double[] lxk_local, lyk_local, lzk_local;
648 private double[] ltxk_local, ltyk_local, ltzk_local;
649 private double[] masking_local;
650 private double[] maskingp_local;
651 private double[] maskingd_local;
652 private int threadID;
653
654 RealSpaceEnergyLoop() {
655 super();
656 dx_local = new double[3];
657 rot_local = new double[3][3];
658 torques = new Torque();
659 }
660
661 @Override
662 public void finish() {
663 sharedInteractions.addAndGet(count);
664 if (lambdaTerm) {
665 shareddEdLambda.addAndGet(dUdL * electric);
666 sharedd2EdLambda2.addAndGet(d2UdL2 * electric);
667 }
668 realSpaceEnergyTime[getThreadIndex()] += System.nanoTime();
669 }
670
671 public int getCount() {
672 return count;
673 }
674
675 @Override
676 public void run(int lb, int ub) {
677 List<SymOp> symOps = crystal.spaceGroup.symOps;
678 int nSymm = symOps.size();
679 int nAtoms = atoms.length;
680 for (iSymm = 0; iSymm < nSymm; iSymm++) {
681 SymOp symOp = symOps.get(iSymm);
682 if (gradient) {
683 fill(gxk_local, 0.0);
684 fill(gyk_local, 0.0);
685 fill(gzk_local, 0.0);
686 fill(txk_local, 0.0);
687 fill(tyk_local, 0.0);
688 fill(tzk_local, 0.0);
689 }
690 if (lambdaTerm) {
691 fill(lxk_local, 0.0);
692 fill(lyk_local, 0.0);
693 fill(lzk_local, 0.0);
694 fill(ltxk_local, 0.0);
695 fill(ltyk_local, 0.0);
696 fill(ltzk_local, 0.0);
697 }
698 realSpaceChunk(lb, ub);
699 if (gradient) {
700
701 int[] frameIndex = {-1, -1, -1, -1};
702 double[][] g = new double[4][3];
703 double[] trq = new double[3];
704 for (int i = 0; i < nAtoms; i++) {
705 fill(frameIndex, -1);
706 for (int j = 0; j < 4; j++) {
707 fill(g[j], 0.0);
708 }
709 trq[0] = txk_local[i];
710 trq[1] = tyk_local[i];
711 trq[2] = tzk_local[i];
712 torques.torque(i, iSymm, trq, frameIndex, g);
713 for (int j = 0; j < 4; j++) {
714 int index = frameIndex[j];
715 if (index >= 0) {
716 double[] gj = g[j];
717 gxk_local[index] += gj[0];
718 gyk_local[index] += gj[1];
719 gzk_local[index] += gj[2];
720 }
721 }
722 }
723
724 if (iSymm != 0) {
725 crystal.applyTransSymRot(
726 nAtoms, gxk_local, gyk_local, gzk_local, gxk_local, gyk_local, gzk_local, symOp,
727 rot_local);
728 }
729
730 for (int j = 0; j < nAtoms; j++) {
731 grad.add(threadID, j, gxk_local[j], gyk_local[j], gzk_local[j]);
732 }
733 }
734 if (lambdaTerm) {
735
736 int[] frameIndex = {-1, -1, -1, -1};
737 double[][] g = new double[4][3];
738 double[] trq = new double[3];
739 for (int i = 0; i < nAtoms; i++) {
740 fill(frameIndex, -1);
741 for (int j = 0; j < 4; j++) {
742 fill(g[j], 0.0);
743 }
744 trq[0] = ltxk_local[i];
745 trq[1] = ltyk_local[i];
746 trq[2] = ltzk_local[i];
747 torques.torque(i, iSymm, trq, frameIndex, g);
748 for (int j = 0; j < 4; j++) {
749 int index = frameIndex[j];
750 if (index >= 0) {
751 double[] gj = g[j];
752 lxk_local[index] += gj[0];
753 lyk_local[index] += gj[1];
754 lzk_local[index] += gj[2];
755 }
756 }
757 }
758
759 if (iSymm != 0) {
760 crystal.applyTransSymRot(
761 nAtoms, lxk_local, lyk_local, lzk_local, lxk_local, lyk_local, lzk_local, symOp,
762 rot_local);
763 }
764
765 for (int j = 0; j < nAtoms; j++) {
766 lambdaGrad.add(threadID, j, lxk_local[j], lyk_local[j], lzk_local[j]);
767 }
768 }
769 }
770 }
771
772 @Override
773 public IntegerSchedule schedule() {
774 return realSpaceSchedule;
775 }
776
777 @Override
778 public void start() {
779 init();
780 threadID = getThreadIndex();
781 realSpaceEnergyTime[threadID] -= System.nanoTime();
782 permanentEnergy = 0.0;
783 inducedEnergy = 0.0;
784 count = 0;
785 if (lambdaTerm) {
786 dUdL = 0.0;
787 d2UdL2 = 0.0;
788 }
789 torques.init(axisAtom, frame, coordinates);
790 }
791
792 private void init() {
793 int nAtoms = atoms.length;
794 if (masking_local == null || masking_local.length < nAtoms) {
795 txk_local = new double[nAtoms];
796 tyk_local = new double[nAtoms];
797 tzk_local = new double[nAtoms];
798 gxk_local = new double[nAtoms];
799 gyk_local = new double[nAtoms];
800 gzk_local = new double[nAtoms];
801 lxk_local = new double[nAtoms];
802 lyk_local = new double[nAtoms];
803 lzk_local = new double[nAtoms];
804 ltxk_local = new double[nAtoms];
805 ltyk_local = new double[nAtoms];
806 ltzk_local = new double[nAtoms];
807 masking_local = new double[nAtoms];
808 maskingp_local = new double[nAtoms];
809 maskingd_local = new double[nAtoms];
810 fill(masking_local, 1.0);
811 fill(maskingp_local, 1.0);
812 fill(maskingd_local, 1.0);
813 }
814 }
815
816
817
818
819
820
821
822 private void realSpaceChunk(final int lb, final int ub) {
823 final double[] x = coordinates[0][0];
824 final double[] y = coordinates[0][1];
825 final double[] z = coordinates[0][2];
826 final double[][] mpole = globalMultipole[0];
827 final double[] zeropole = new double[10];
828 final double[][] ind = inducedDipole[0];
829 final double[][] indp = inducedDipoleCR[0];
830 final int[][] lists = realSpaceLists[iSymm];
831 final double[] neighborX = coordinates[iSymm][0];
832 final double[] neighborY = coordinates[iSymm][1];
833 final double[] neighborZ = coordinates[iSymm][2];
834 final double[][] neighborMultipole = globalMultipole[iSymm];
835 final double[][] neighborInducedDipole = inducedDipole[iSymm];
836 final double[][] neighborInducedDipolep = inducedDipoleCR[iSymm];
837 for (i = lb; i <= ub; i++) {
838 if (!use[i]) {
839 continue;
840 }
841 final int moleculei = molecule[i];
842 if (iSymm == 0) {
843 applyMask(i, null, masking_local, maskingp_local, maskingd_local);
844 }
845 final double xi = x[i];
846 final double yi = y[i];
847 final double zi = z[i];
848 final double[] globalMultipolei = mpole[i];
849 final double[] inducedDipolei = ind[i];
850 final double[] inducedDipolepi = indp[i];
851 setMultipoleI(globalMultipolei);
852 setInducedI(inducedDipolei);
853 setInducedpI(inducedDipolepi);
854 final boolean softi = isSoft[i];
855 final double pdi = ipdamp[i];
856 final double pti = thole[i];
857 final int[] list = lists[i];
858 final int npair = realSpaceCounts[iSymm][i];
859 for (int j = 0; j < npair; j++) {
860 k = list[j];
861 if (!use[k]) {
862 continue;
863 }
864 boolean sameMolecule = (moleculei == molecule[k]);
865 if (lambdaMode == LambdaMode.VAPOR) {
866 if ((intermolecularSoftcore && !sameMolecule)
867 || (intramolecularSoftcore && sameMolecule)) {
868 continue;
869 }
870 }
871 selfScale = 1.0;
872 if (i == k) {
873 selfScale = 0.5;
874 }
875 double beta = 0.0;
876 l2 = 1.0;
877 soft = (softi || isSoft[k]);
878 if (soft && doPermanentRealSpace) {
879 beta = lAlpha;
880 l2 = permanentScale;
881 } else if (nnTerm) {
882 l2 = permanentScale;
883 }
884 final double xk = neighborX[k];
885 final double yk = neighborY[k];
886 final double zk = neighborZ[k];
887 dx_local[0] = xk - xi;
888 dx_local[1] = yk - yi;
889 dx_local[2] = zk - zi;
890 double r2 = crystal.image(dx_local);
891 xr = dx_local[0];
892 yr = dx_local[1];
893 zr = dx_local[2];
894 final double[] globalMultipolek = neighborMultipole[k];
895 final double[] inducedDipolek = neighborInducedDipole[k];
896 final double[] inducedDipolepk = neighborInducedDipolep[k];
897 setMultipoleK(globalMultipolek);
898 setInducedK(inducedDipolek);
899 setInducedpK(inducedDipolepk);
900 final double pdk = ipdamp[k];
901 final double ptk = thole[k];
902 scale = masking_local[k];
903 scalep = maskingp_local[k];
904 scaled = maskingd_local[k];
905 scale3 = 1.0;
906 scale5 = 1.0;
907 scale7 = 1.0;
908 double r = sqrt(r2 + beta);
909 double ralpha = aewald * r;
910 double exp2a = exp(-ralpha * ralpha);
911 rr1 = 1.0 / r;
912 double rr2 = rr1 * rr1;
913 bn0 = erfc(ralpha) * rr1;
914 bn1 = (bn0 + an0 * exp2a) * rr2;
915 bn2 = (3.0 * bn1 + an1 * exp2a) * rr2;
916 bn3 = (5.0 * bn2 + an2 * exp2a) * rr2;
917 bn4 = (7.0 * bn3 + an3 * exp2a) * rr2;
918 bn5 = (9.0 * bn4 + an4 * exp2a) * rr2;
919 bn6 = (11.0 * bn5 + an5 * exp2a) * rr2;
920 rr3 = rr1 * rr2;
921 rr5 = 3.0 * rr3 * rr2;
922 rr7 = 5.0 * rr5 * rr2;
923 rr9 = 7.0 * rr7 * rr2;
924 rr11 = 9.0 * rr9 * rr2;
925 rr13 = 11.0 * rr11 * rr2;
926 ddsc3x = 0.0;
927 ddsc3y = 0.0;
928 ddsc3z = 0.0;
929 ddsc5x = 0.0;
930 ddsc5y = 0.0;
931 ddsc5z = 0.0;
932 ddsc7x = 0.0;
933 ddsc7y = 0.0;
934 ddsc7z = 0.0;
935 double damp = pdi * pdk;
936 double thole = min(pti, ptk);
937 double rdamp = r * damp;
938 damp = -thole * rdamp * rdamp * rdamp;
939 if (damp > -50.0) {
940 final double expdamp = exp(damp);
941 scale3 = 1.0 - expdamp;
942 scale5 = 1.0 - expdamp * (1.0 - damp);
943 scale7 = 1.0 - expdamp * (1.0 - damp + 0.6 * damp * damp);
944 final double temp3 = -3.0 * damp * expdamp * rr2;
945 final double temp5 = -damp;
946 final double temp7 = -0.2 - 0.6 * damp;
947 ddsc3x = temp3 * xr;
948 ddsc3y = temp3 * yr;
949 ddsc3z = temp3 * zr;
950 ddsc5x = temp5 * ddsc3x;
951 ddsc5y = temp5 * ddsc3y;
952 ddsc5z = temp5 * ddsc3z;
953 ddsc7x = temp7 * ddsc5x;
954 ddsc7y = temp7 * ddsc5y;
955 ddsc7z = temp7 * ddsc5z;
956 }
957 if (doPermanentRealSpace) {
958 double ei = permanentPair(gradient, lambdaTerm);
959 if (isNaN(ei) || isInfinite(ei)) {
960 String message = format(" %s\n %s\n %s\n The permanent multipole energy between "
961 + "atoms %d and %d (%d) is %16.8f at %16.8f A.",
962 crystal.getUnitCell().toString(), atoms[i].toString(), atoms[k].toString(),
963 i, k, iSymm, ei, r);
964 throw new EnergyException(message);
965 }
966 if (ei != 0.0) {
967 permanentEnergy += ei;
968 count++;
969
970 }
971 if (esvTerm) {
972 if (extendedSystem.isTitrating(i)) {
973 double titrdUdL = 0.0;
974 double tautdUdL = 0.0;
975 final double[][] titrMpole = titrationMultipole[0];
976 final double[] titrMultipolei = titrMpole[i];
977 setMultipoleI(titrMultipolei);
978 titrdUdL = electric * permanentPair(false, false);
979 if (extendedSystem.isTautomerizing(i)) {
980 final double[][] tautMpole = tautomerMultipole[0];
981 final double[] tautMultipolei = tautMpole[i];
982 setMultipoleI(tautMultipolei);
983 tautdUdL = electric * permanentPair(false, false);
984 }
985 extendedSystem.addPermElecDeriv(i, titrdUdL, tautdUdL);
986
987 setMultipoleI(globalMultipolei);
988 }
989 if (extendedSystem.isTitrating(k)) {
990 double titrdUdL = 0.0;
991 double tautdUdL = 0.0;
992 final double[][] titrNeighborMpole = titrationMultipole[iSymm];
993 final double[] titrMultipolek = titrNeighborMpole[k];
994 setMultipoleK(titrMultipolek);
995 titrdUdL = electric * permanentPair(false, false);
996 if (extendedSystem.isTautomerizing(k)) {
997 final double[][] tautNeighborMpole = tautomerMultipole[iSymm];
998 final double[] tautMultipolek = tautNeighborMpole[k];
999 setMultipoleK(tautMultipolek);
1000 tautdUdL = electric * permanentPair(false, false);
1001 }
1002 extendedSystem.addPermElecDeriv(k, titrdUdL, tautdUdL);
1003
1004 setMultipoleK(globalMultipolek);
1005 }
1006 }
1007 }
1008 if (polarization != Polarization.NONE && doPolarization) {
1009
1010 if (soft && doPermanentRealSpace) {
1011 scale3 = 1.0;
1012 scale5 = 1.0;
1013 scale7 = 1.0;
1014 r = sqrt(r2);
1015 ralpha = aewald * r;
1016 exp2a = exp(-ralpha * ralpha);
1017 rr1 = 1.0 / r;
1018 rr2 = rr1 * rr1;
1019 bn0 = erfc(ralpha) * rr1;
1020 bn1 = (bn0 + an0 * exp2a) * rr2;
1021 bn2 = (3.0 * bn1 + an1 * exp2a) * rr2;
1022 bn3 = (5.0 * bn2 + an2 * exp2a) * rr2;
1023 bn4 = (7.0 * bn3 + an3 * exp2a) * rr2;
1024 bn5 = (9.0 * bn4 + an4 * exp2a) * rr2;
1025 bn6 = (11.0 * bn5 + an5 * exp2a) * rr2;
1026 rr3 = rr1 * rr2;
1027 rr5 = 3.0 * rr3 * rr2;
1028 rr7 = 5.0 * rr5 * rr2;
1029 rr9 = 7.0 * rr7 * rr2;
1030 rr11 = 9.0 * rr9 * rr2;
1031 ddsc3x = 0.0;
1032 ddsc3y = 0.0;
1033 ddsc3z = 0.0;
1034 ddsc5x = 0.0;
1035 ddsc5y = 0.0;
1036 ddsc5z = 0.0;
1037 ddsc7x = 0.0;
1038 ddsc7y = 0.0;
1039 ddsc7z = 0.0;
1040 damp = pdi * pdk;
1041 thole = min(pti, ptk);
1042 rdamp = r * damp;
1043 damp = -thole * rdamp * rdamp * rdamp;
1044 if (damp > -50.0) {
1045 final double expdamp = exp(damp);
1046 scale3 = 1.0 - expdamp;
1047 scale5 = 1.0 - expdamp * (1.0 - damp);
1048 scale7 = 1.0 - expdamp * (1.0 - damp + 0.6 * damp * damp);
1049 final double temp3 = -3.0 * damp * expdamp * rr2;
1050 final double temp5 = -damp;
1051 final double temp7 = -0.2 - 0.6 * damp;
1052 ddsc3x = temp3 * xr;
1053 ddsc3y = temp3 * yr;
1054 ddsc3z = temp3 * zr;
1055 ddsc5x = temp5 * ddsc3x;
1056 ddsc5y = temp5 * ddsc3y;
1057 ddsc5z = temp5 * ddsc3z;
1058 ddsc7x = temp7 * ddsc5x;
1059 ddsc7y = temp7 * ddsc5y;
1060 ddsc7z = temp7 * ddsc5z;
1061 }
1062 }
1063 double ei = polarizationPair(gradient, lambdaTerm);
1064 if (isNaN(ei) || isInfinite(ei)) {
1065 String message = format(" %s\n"
1066 + " %s\n with induced dipole: %8.3f %8.3f %8.3f\n"
1067 + " %s\n with induced dipole: %8.3f %8.3f %8.3f\n"
1068 + " The polarization energy due to atoms "
1069 + "%d and %d (%d) is %10.6f at %10.6f A.",
1070 crystal.getUnitCell(), atoms[i], uix, uiy, uiz, atoms[k], ukx, uky, ukz, i + 1, k + 1, iSymm, ei, r);
1071 throw new EnergyException(message);
1072 }
1073 inducedEnergy += ei;
1074 if (esvTerm) {
1075 int esvI = extendedSystem.getTitrationESVIndex(i);
1076 int esvK = extendedSystem.getTitrationESVIndex(k);
1077 if (extendedSystem.isTitrating(i)) {
1078 double titrdUdL = 0.0;
1079 double tautdUdL = 0.0;
1080 final double[][] titrMpole = titrationMultipole[0];
1081 final double[] titrMultipolei = titrMpole[i];
1082 setMultipoleI(titrMultipolei);
1083
1084 if (extendedSystem.isTitrating(k) && esvI == esvK) {
1085 final double[][] titrNeighborMpole = titrationMultipole[iSymm];
1086 final double[] titrMultipolek = titrNeighborMpole[k];
1087 setMultipoleK(titrMultipolek);
1088 } else {
1089 setMultipoleK(zeropole);
1090 }
1091 titrdUdL = polarizationPair(false, false);
1092
1093 setInducedI(inducedDipolepi);
1094 setInducedK(inducedDipolepk);
1095 scaled = maskingp_local[k];
1096 scalep = maskingd_local[k];
1097 titrdUdL += polarizationPair(false, false);
1098
1099 setInducedI(inducedDipolei);
1100 setInducedK(inducedDipolek);
1101 scalep = maskingp_local[k];
1102 scaled = maskingd_local[k];
1103
1104 if (extendedSystem.isTautomerizing(i)) {
1105 final double[][] tautMpole = tautomerMultipole[0];
1106 final double[] tautMultipolei = tautMpole[i];
1107 setMultipoleI(tautMultipolei);
1108
1109 if (extendedSystem.isTautomerizing(k) && esvI == esvK) {
1110 final double[][] tautNeighborMpole = tautomerMultipole[iSymm];
1111 final double[] tautMultipolek = tautNeighborMpole[k];
1112 setMultipoleK(tautMultipolek);
1113 } else {
1114 setMultipoleK(zeropole);
1115 }
1116 tautdUdL = polarizationPair(false, false);
1117
1118 setInducedI(inducedDipolepi);
1119 setInducedK(inducedDipolepk);
1120 scaled = maskingp_local[k];
1121 scalep = maskingd_local[k];
1122 tautdUdL += polarizationPair(false, false);
1123
1124 setInducedI(inducedDipolei);
1125 setInducedK(inducedDipolek);
1126 scalep = maskingp_local[k];
1127 scaled = maskingd_local[k];
1128 }
1129 extendedSystem.addIndElecDeriv(i, titrdUdL * electric, tautdUdL * electric);
1130
1131 setMultipoleI(globalMultipolei);
1132 setMultipoleK(globalMultipolek);
1133 }
1134
1135 if (extendedSystem.isTitrating(k) && esvI != esvK) {
1136 double titrdUdL = 0.0;
1137 double tautdUdL = 0.0;
1138 final double[][] titrNeighborMpole = titrationMultipole[iSymm];
1139 final double[] titrMultipolek = titrNeighborMpole[k];
1140 setMultipoleK(titrMultipolek);
1141 setMultipoleI(zeropole);
1142 titrdUdL = polarizationPair(false, false);
1143
1144 setInducedI(inducedDipolepi);
1145 setInducedK(inducedDipolepk);
1146 scaled = maskingp_local[k];
1147 scalep = maskingd_local[k];
1148 titrdUdL += polarizationPair(false, false);
1149
1150 setInducedI(inducedDipolei);
1151 setInducedK(inducedDipolek);
1152 scalep = maskingp_local[k];
1153 scaled = maskingd_local[k];
1154 if (extendedSystem.isTautomerizing(k)) {
1155 final double[][] tautNeighborMpole = tautomerMultipole[iSymm];
1156 final double[] tautMultipolek = tautNeighborMpole[k];
1157 setMultipoleK(tautMultipolek);
1158 tautdUdL = polarizationPair(false, false);
1159
1160 setInducedI(inducedDipolepi);
1161 setInducedK(inducedDipolepk);
1162 scaled = maskingp_local[k];
1163 scalep = maskingd_local[k];
1164 tautdUdL += polarizationPair(false, false);
1165
1166 setInducedI(inducedDipolei);
1167 setInducedK(inducedDipolek);
1168 scalep = maskingp_local[k];
1169 scaled = maskingd_local[k];
1170 }
1171 extendedSystem.addIndElecDeriv(k, titrdUdL * electric, tautdUdL * electric);
1172
1173 setMultipoleI(globalMultipolei);
1174 setMultipoleK(globalMultipolek);
1175 }
1176 }
1177 }
1178 }
1179 if (iSymm == 0) {
1180 removeMask(i, null, masking_local, maskingp_local, maskingd_local);
1181 }
1182 }
1183 }
1184
1185
1186
1187
1188
1189
1190 private double permanentPair(boolean gradientLocal, boolean lambdaTermLocal) {
1191 final double dixdkx = diy * dkz - diz * dky;
1192 final double dixdky = diz * dkx - dix * dkz;
1193 final double dixdkz = dix * dky - diy * dkx;
1194 final double dixrx = diy * zr - diz * yr;
1195 final double dixry = diz * xr - dix * zr;
1196 final double dixrz = dix * yr - diy * xr;
1197 final double dkxrx = dky * zr - dkz * yr;
1198 final double dkxry = dkz * xr - dkx * zr;
1199 final double dkxrz = dkx * yr - dky * xr;
1200 final double qirx = qixx * xr + qixy * yr + qixz * zr;
1201 final double qiry = qixy * xr + qiyy * yr + qiyz * zr;
1202 final double qirz = qixz * xr + qiyz * yr + qizz * zr;
1203 final double qkrx = qkxx * xr + qkxy * yr + qkxz * zr;
1204 final double qkry = qkxy * xr + qkyy * yr + qkyz * zr;
1205 final double qkrz = qkxz * xr + qkyz * yr + qkzz * zr;
1206 final double qiqkrx = qixx * qkrx + qixy * qkry + qixz * qkrz;
1207 final double qiqkry = qixy * qkrx + qiyy * qkry + qiyz * qkrz;
1208 final double qiqkrz = qixz * qkrx + qiyz * qkry + qizz * qkrz;
1209 final double qkqirx = qkxx * qirx + qkxy * qiry + qkxz * qirz;
1210 final double qkqiry = qkxy * qirx + qkyy * qiry + qkyz * qirz;
1211 final double qkqirz = qkxz * qirx + qkyz * qiry + qkzz * qirz;
1212 final double qixqkx =
1213 qixy * qkxz + qiyy * qkyz + qiyz * qkzz - qixz * qkxy - qiyz * qkyy - qizz * qkyz;
1214 final double qixqky =
1215 qixz * qkxx + qiyz * qkxy + qizz * qkxz - qixx * qkxz - qixy * qkyz - qixz * qkzz;
1216 final double qixqkz =
1217 qixx * qkxy + qixy * qkyy + qixz * qkyz - qixy * qkxx - qiyy * qkxy - qiyz * qkxz;
1218 final double rxqirx = yr * qirz - zr * qiry;
1219 final double rxqiry = zr * qirx - xr * qirz;
1220 final double rxqirz = xr * qiry - yr * qirx;
1221 final double rxqkrx = yr * qkrz - zr * qkry;
1222 final double rxqkry = zr * qkrx - xr * qkrz;
1223 final double rxqkrz = xr * qkry - yr * qkrx;
1224 final double rxqikrx = yr * qiqkrz - zr * qiqkry;
1225 final double rxqikry = zr * qiqkrx - xr * qiqkrz;
1226 final double rxqikrz = xr * qiqkry - yr * qiqkrx;
1227 final double rxqkirx = yr * qkqirz - zr * qkqiry;
1228 final double rxqkiry = zr * qkqirx - xr * qkqirz;
1229 final double rxqkirz = xr * qkqiry - yr * qkqirx;
1230 final double qkrxqirx = qkry * qirz - qkrz * qiry;
1231 final double qkrxqiry = qkrz * qirx - qkrx * qirz;
1232 final double qkrxqirz = qkrx * qiry - qkry * qirx;
1233 final double qidkx = qixx * dkx + qixy * dky + qixz * dkz;
1234 final double qidky = qixy * dkx + qiyy * dky + qiyz * dkz;
1235 final double qidkz = qixz * dkx + qiyz * dky + qizz * dkz;
1236 final double qkdix = qkxx * dix + qkxy * diy + qkxz * diz;
1237 final double qkdiy = qkxy * dix + qkyy * diy + qkyz * diz;
1238 final double qkdiz = qkxz * dix + qkyz * diy + qkzz * diz;
1239 final double dixqkrx = diy * qkrz - diz * qkry;
1240 final double dixqkry = diz * qkrx - dix * qkrz;
1241 final double dixqkrz = dix * qkry - diy * qkrx;
1242 final double dkxqirx = dky * qirz - dkz * qiry;
1243 final double dkxqiry = dkz * qirx - dkx * qirz;
1244 final double dkxqirz = dkx * qiry - dky * qirx;
1245 final double rxqidkx = yr * qidkz - zr * qidky;
1246 final double rxqidky = zr * qidkx - xr * qidkz;
1247 final double rxqidkz = xr * qidky - yr * qidkx;
1248 final double rxqkdix = yr * qkdiz - zr * qkdiy;
1249 final double rxqkdiy = zr * qkdix - xr * qkdiz;
1250 final double rxqkdiz = xr * qkdiy - yr * qkdix;
1251
1252
1253 final double sc2 = dix * dkx + diy * dky + diz * dkz;
1254 final double sc3 = dix * xr + diy * yr + diz * zr;
1255 final double sc4 = dkx * xr + dky * yr + dkz * zr;
1256 final double sc5 = qirx * xr + qiry * yr + qirz * zr;
1257 final double sc6 = qkrx * xr + qkry * yr + qkrz * zr;
1258 final double sc7 = qirx * dkx + qiry * dky + qirz * dkz;
1259 final double sc8 = qkrx * dix + qkry * diy + qkrz * diz;
1260 final double sc9 = qirx * qkrx + qiry * qkry + qirz * qkrz;
1261 final double sc10 =
1262 2.0 * (qixy * qkxy + qixz * qkxz + qiyz * qkyz) + qixx * qkxx + qiyy * qkyy + qizz * qkzz;
1263
1264
1265 final double gl0 = ci * ck;
1266 final double gl1 = ck * sc3 - ci * sc4;
1267 final double gl2 = ci * sc6 + ck * sc5 - sc3 * sc4;
1268 final double gl3 = sc3 * sc6 - sc4 * sc5;
1269 final double gl4 = sc5 * sc6;
1270 final double gl5 = -4.0 * sc9;
1271 final double gl6 = sc2;
1272 final double gl7 = 2.0 * (sc7 - sc8);
1273 final double gl8 = 2.0 * sc10;
1274
1275
1276 final double scale1 = 1.0 - scale;
1277 final double ereal =
1278 gl0 * bn0 + (gl1 + gl6) * bn1 + (gl2 + gl7 + gl8) * bn2 + (gl3 + gl5) * bn3 + gl4 * bn4;
1279 final double efix =
1280 scale1
1281 * (gl0 * rr1
1282 + (gl1 + gl6) * rr3
1283 + (gl2 + gl7 + gl8) * rr5
1284 + (gl3 + gl5) * rr7
1285 + gl4 * rr9);
1286 final double e = selfScale * l2 * (ereal - efix);
1287 if (gradientLocal) {
1288 final double gf1 =
1289 bn1 * gl0 + bn2 * (gl1 + gl6) + bn3 * (gl2 + gl7 + gl8) + bn4 * (gl3 + gl5) + bn5 * gl4;
1290 final double gf2 = -ck * bn1 + sc4 * bn2 - sc6 * bn3;
1291 final double gf3 = ci * bn1 + sc3 * bn2 + sc5 * bn3;
1292 final double gf4 = 2.0 * bn2;
1293 final double gf5 = 2.0 * (-ck * bn2 + sc4 * bn3 - sc6 * bn4);
1294 final double gf6 = 2.0 * (-ci * bn2 - sc3 * bn3 - sc5 * bn4);
1295 final double gf7 = 4.0 * bn3;
1296
1297
1298 double ftm2x =
1299 gf1 * xr
1300 + gf2 * dix
1301 + gf3 * dkx
1302 + gf4 * (qkdix - qidkx)
1303 + gf5 * qirx
1304 + gf6 * qkrx
1305 + gf7 * (qiqkrx + qkqirx);
1306 double ftm2y =
1307 gf1 * yr
1308 + gf2 * diy
1309 + gf3 * dky
1310 + gf4 * (qkdiy - qidky)
1311 + gf5 * qiry
1312 + gf6 * qkry
1313 + gf7 * (qiqkry + qkqiry);
1314 double ftm2z =
1315 gf1 * zr
1316 + gf2 * diz
1317 + gf3 * dkz
1318 + gf4 * (qkdiz - qidkz)
1319 + gf5 * qirz
1320 + gf6 * qkrz
1321 + gf7 * (qiqkrz + qkqirz);
1322
1323
1324 double ttm2x =
1325 -bn1 * dixdkx
1326 + gf2 * dixrx
1327 + gf4 * (dixqkrx + dkxqirx + rxqidkx - 2.0 * qixqkx)
1328 - gf5 * rxqirx
1329 - gf7 * (rxqikrx + qkrxqirx);
1330 double ttm2y =
1331 -bn1 * dixdky
1332 + gf2 * dixry
1333 + gf4 * (dixqkry + dkxqiry + rxqidky - 2.0 * qixqky)
1334 - gf5 * rxqiry
1335 - gf7 * (rxqikry + qkrxqiry);
1336 double ttm2z =
1337 -bn1 * dixdkz
1338 + gf2 * dixrz
1339 + gf4 * (dixqkrz + dkxqirz + rxqidkz - 2.0 * qixqkz)
1340 - gf5 * rxqirz
1341 - gf7 * (rxqikrz + qkrxqirz);
1342 double ttm3x =
1343 bn1 * dixdkx
1344 + gf3 * dkxrx
1345 - gf4 * (dixqkrx + dkxqirx + rxqkdix - 2.0 * qixqkx)
1346 - gf6 * rxqkrx
1347 - gf7 * (rxqkirx - qkrxqirx);
1348 double ttm3y =
1349 bn1 * dixdky
1350 + gf3 * dkxry
1351 - gf4 * (dixqkry + dkxqiry + rxqkdiy - 2.0 * qixqky)
1352 - gf6 * rxqkry
1353 - gf7 * (rxqkiry - qkrxqiry);
1354 double ttm3z =
1355 bn1 * dixdkz
1356 + gf3 * dkxrz
1357 - gf4 * (dixqkrz + dkxqirz + rxqkdiz - 2.0 * qixqkz)
1358 - gf6 * rxqkrz
1359 - gf7 * (rxqkirz - qkrxqirz);
1360
1361
1362 if (scale1 != 0.0) {
1363 final double gfr1 =
1364 rr3 * gl0
1365 + rr5 * (gl1 + gl6)
1366 + rr7 * (gl2 + gl7 + gl8)
1367 + rr9 * (gl3 + gl5)
1368 + rr11 * gl4;
1369 final double gfr2 = -ck * rr3 + sc4 * rr5 - sc6 * rr7;
1370 final double gfr3 = ci * rr3 + sc3 * rr5 + sc5 * rr7;
1371 final double gfr4 = 2.0 * rr5;
1372 final double gfr5 = 2.0 * (-ck * rr5 + sc4 * rr7 - sc6 * rr9);
1373 final double gfr6 = 2.0 * (-ci * rr5 - sc3 * rr7 - sc5 * rr9);
1374 final double gfr7 = 4.0 * rr7;
1375
1376
1377 final double ftm2rx =
1378 gfr1 * xr
1379 + gfr2 * dix
1380 + gfr3 * dkx
1381 + gfr4 * (qkdix - qidkx)
1382 + gfr5 * qirx
1383 + gfr6 * qkrx
1384 + gfr7 * (qiqkrx + qkqirx);
1385 final double ftm2ry =
1386 gfr1 * yr
1387 + gfr2 * diy
1388 + gfr3 * dky
1389 + gfr4 * (qkdiy - qidky)
1390 + gfr5 * qiry
1391 + gfr6 * qkry
1392 + gfr7 * (qiqkry + qkqiry);
1393 final double ftm2rz =
1394 gfr1 * zr
1395 + gfr2 * diz
1396 + gfr3 * dkz
1397 + gfr4 * (qkdiz - qidkz)
1398 + gfr5 * qirz
1399 + gfr6 * qkrz
1400 + gfr7 * (qiqkrz + qkqirz);
1401
1402
1403 final double ttm2rx =
1404 -rr3 * dixdkx
1405 + gfr2 * dixrx
1406 + gfr4 * (dixqkrx + dkxqirx + rxqidkx - 2.0 * qixqkx)
1407 - gfr5 * rxqirx
1408 - gfr7 * (rxqikrx + qkrxqirx);
1409 final double ttm2ry =
1410 -rr3 * dixdky
1411 + gfr2 * dixry
1412 + gfr4 * (dixqkry + dkxqiry + rxqidky - 2.0 * qixqky)
1413 - gfr5 * rxqiry
1414 - gfr7 * (rxqikry + qkrxqiry);
1415 final double ttm2rz =
1416 -rr3 * dixdkz
1417 + gfr2 * dixrz
1418 + gfr4 * (dixqkrz + dkxqirz + rxqidkz - 2.0 * qixqkz)
1419 - gfr5 * rxqirz
1420 - gfr7 * (rxqikrz + qkrxqirz);
1421 final double ttm3rx =
1422 rr3 * dixdkx
1423 + gfr3 * dkxrx
1424 - gfr4 * (dixqkrx + dkxqirx + rxqkdix - 2.0 * qixqkx)
1425 - gfr6 * rxqkrx
1426 - gfr7 * (rxqkirx - qkrxqirx);
1427 final double ttm3ry =
1428 rr3 * dixdky
1429 + gfr3 * dkxry
1430 - gfr4 * (dixqkry + dkxqiry + rxqkdiy - 2.0 * qixqky)
1431 - gfr6 * rxqkry
1432 - gfr7 * (rxqkiry - qkrxqiry);
1433 final double ttm3rz =
1434 rr3 * dixdkz
1435 + gfr3 * dkxrz
1436 - gfr4 * (dixqkrz + dkxqirz + rxqkdiz - 2.0 * qixqkz)
1437 - gfr6 * rxqkrz
1438 - gfr7 * (rxqkirz - qkrxqirz);
1439 ftm2x -= scale1 * ftm2rx;
1440 ftm2y -= scale1 * ftm2ry;
1441 ftm2z -= scale1 * ftm2rz;
1442 ttm2x -= scale1 * ttm2rx;
1443 ttm2y -= scale1 * ttm2ry;
1444 ttm2z -= scale1 * ttm2rz;
1445 ttm3x -= scale1 * ttm3rx;
1446 ttm3y -= scale1 * ttm3ry;
1447 ttm3z -= scale1 * ttm3rz;
1448 }
1449 double prefactor = electric * selfScale * l2;
1450 grad.add(threadID, i, prefactor * ftm2x, prefactor * ftm2y, prefactor * ftm2z);
1451 torque.add(threadID, i, prefactor * ttm2x, prefactor * ttm2y, prefactor * ttm2z);
1452
1453
1454
1455
1456
1457 gxk_local[k] -= prefactor * ftm2x;
1458 gyk_local[k] -= prefactor * ftm2y;
1459 gzk_local[k] -= prefactor * ftm2z;
1460 txk_local[k] += prefactor * ttm3x;
1461 tyk_local[k] += prefactor * ttm3y;
1462 tzk_local[k] += prefactor * ttm3z;
1463
1464
1465 if (lambdaTerm && soft) {
1466 prefactor = electric * selfScale * dEdLSign * dlPowPerm;
1467 lambdaGrad.add(threadID, i, prefactor * ftm2x, prefactor * ftm2y, prefactor * ftm2z);
1468 lambdaTorque.add(threadID, i, prefactor * ttm2x, prefactor * ttm2y, prefactor * ttm2z);
1469 lxk_local[k] -= prefactor * ftm2x;
1470 lyk_local[k] -= prefactor * ftm2y;
1471 lzk_local[k] -= prefactor * ftm2z;
1472 ltxk_local[k] += prefactor * ttm3x;
1473 ltyk_local[k] += prefactor * ttm3y;
1474 ltzk_local[k] += prefactor * ttm3z;
1475 }
1476 }
1477 if (lambdaTermLocal && soft) {
1478 double dRealdL =
1479 gl0 * bn1 + (gl1 + gl6) * bn2 + (gl2 + gl7 + gl8) * bn3 + (gl3 + gl5) * bn4 + gl4 * bn5;
1480 double d2RealdL2 =
1481 gl0 * bn2 + (gl1 + gl6) * bn3 + (gl2 + gl7 + gl8) * bn4 + (gl3 + gl5) * bn5 + gl4 * bn6;
1482
1483 dUdL += selfScale * (dEdLSign * dlPowPerm * ereal + l2 * dlAlpha * dRealdL);
1484 d2UdL2 +=
1485 selfScale
1486 * (dEdLSign
1487 * (d2lPowPerm * ereal
1488 + dlPowPerm * dlAlpha * dRealdL
1489 + dlPowPerm * dlAlpha * dRealdL)
1490 + l2 * d2lAlpha * dRealdL
1491 + l2 * dlAlpha * dlAlpha * d2RealdL2);
1492
1493 double dFixdL =
1494 gl0 * rr3
1495 + (gl1 + gl6) * rr5
1496 + (gl2 + gl7 + gl8) * rr7
1497 + (gl3 + gl5) * rr9
1498 + gl4 * rr11;
1499 double d2FixdL2 =
1500 gl0 * rr5
1501 + (gl1 + gl6) * rr7
1502 + (gl2 + gl7 + gl8) * rr9
1503 + (gl3 + gl5) * rr11
1504 + gl4 * rr13;
1505 dFixdL *= scale1;
1506 d2FixdL2 *= scale1;
1507 dUdL -= selfScale * (dEdLSign * dlPowPerm * efix + l2 * dlAlpha * dFixdL);
1508 d2UdL2 -=
1509 selfScale
1510 * (dEdLSign
1511 * (d2lPowPerm * efix
1512 + dlPowPerm * dlAlpha * dFixdL
1513 + dlPowPerm * dlAlpha * dFixdL)
1514 + l2 * d2lAlpha * dFixdL
1515 + l2 * dlAlpha * dlAlpha * d2FixdL2);
1516
1517
1518 final double gf1 =
1519 bn2 * gl0 + bn3 * (gl1 + gl6) + bn4 * (gl2 + gl7 + gl8) + bn5 * (gl3 + gl5) + bn6 * gl4;
1520 final double gf2 = -ck * bn2 + sc4 * bn3 - sc6 * bn4;
1521 final double gf3 = ci * bn2 + sc3 * bn3 + sc5 * bn4;
1522 final double gf4 = 2.0 * bn3;
1523 final double gf5 = 2.0 * (-ck * bn3 + sc4 * bn4 - sc6 * bn5);
1524 final double gf6 = 2.0 * (-ci * bn3 - sc3 * bn4 - sc5 * bn5);
1525 final double gf7 = 4.0 * bn4;
1526
1527
1528 double ftm2x =
1529 gf1 * xr
1530 + gf2 * dix
1531 + gf3 * dkx
1532 + gf4 * (qkdix - qidkx)
1533 + gf5 * qirx
1534 + gf6 * qkrx
1535 + gf7 * (qiqkrx + qkqirx);
1536 double ftm2y =
1537 gf1 * yr
1538 + gf2 * diy
1539 + gf3 * dky
1540 + gf4 * (qkdiy - qidky)
1541 + gf5 * qiry
1542 + gf6 * qkry
1543 + gf7 * (qiqkry + qkqiry);
1544 double ftm2z =
1545 gf1 * zr
1546 + gf2 * diz
1547 + gf3 * dkz
1548 + gf4 * (qkdiz - qidkz)
1549 + gf5 * qirz
1550 + gf6 * qkrz
1551 + gf7 * (qiqkrz + qkqirz);
1552
1553
1554 double ttm2x =
1555 -bn2 * dixdkx
1556 + gf2 * dixrx
1557 + gf4 * (dixqkrx + dkxqirx + rxqidkx - 2.0 * qixqkx)
1558 - gf5 * rxqirx
1559 - gf7 * (rxqikrx + qkrxqirx);
1560 double ttm2y =
1561 -bn2 * dixdky
1562 + gf2 * dixry
1563 + gf4 * (dixqkry + dkxqiry + rxqidky - 2.0 * qixqky)
1564 - gf5 * rxqiry
1565 - gf7 * (rxqikry + qkrxqiry);
1566 double ttm2z =
1567 -bn2 * dixdkz
1568 + gf2 * dixrz
1569 + gf4 * (dixqkrz + dkxqirz + rxqidkz - 2.0 * qixqkz)
1570 - gf5 * rxqirz
1571 - gf7 * (rxqikrz + qkrxqirz);
1572 double ttm3x =
1573 bn2 * dixdkx
1574 + gf3 * dkxrx
1575 - gf4 * (dixqkrx + dkxqirx + rxqkdix - 2.0 * qixqkx)
1576 - gf6 * rxqkrx
1577 - gf7 * (rxqkirx - qkrxqirx);
1578 double ttm3y =
1579 bn2 * dixdky
1580 + gf3 * dkxry
1581 - gf4 * (dixqkry + dkxqiry + rxqkdiy - 2.0 * qixqky)
1582 - gf6 * rxqkry
1583 - gf7 * (rxqkiry - qkrxqiry);
1584 double ttm3z =
1585 bn2 * dixdkz
1586 + gf3 * dkxrz
1587 - gf4 * (dixqkrz + dkxqirz + rxqkdiz - 2.0 * qixqkz)
1588 - gf6 * rxqkrz
1589 - gf7 * (rxqkirz - qkrxqirz);
1590
1591
1592 if (scale1 != 0.0) {
1593 final double gfr1 =
1594 rr5 * gl0
1595 + rr7 * (gl1 + gl6)
1596 + rr9 * (gl2 + gl7 + gl8)
1597 + rr11 * (gl3 + gl5)
1598 + rr13 * gl4;
1599 final double gfr2 = -ck * rr5 + sc4 * rr7 - sc6 * rr9;
1600 final double gfr3 = ci * rr5 + sc3 * rr7 + sc5 * rr9;
1601 final double gfr4 = 2.0 * rr7;
1602 final double gfr5 = 2.0 * (-ck * rr7 + sc4 * rr9 - sc6 * rr11);
1603 final double gfr6 = 2.0 * (-ci * rr7 - sc3 * rr9 - sc5 * rr11);
1604 final double gfr7 = 4.0 * rr9;
1605
1606
1607 final double ftm2rx =
1608 gfr1 * xr
1609 + gfr2 * dix
1610 + gfr3 * dkx
1611 + gfr4 * (qkdix - qidkx)
1612 + gfr5 * qirx
1613 + gfr6 * qkrx
1614 + gfr7 * (qiqkrx + qkqirx);
1615 final double ftm2ry =
1616 gfr1 * yr
1617 + gfr2 * diy
1618 + gfr3 * dky
1619 + gfr4 * (qkdiy - qidky)
1620 + gfr5 * qiry
1621 + gfr6 * qkry
1622 + gfr7 * (qiqkry + qkqiry);
1623 final double ftm2rz =
1624 gfr1 * zr
1625 + gfr2 * diz
1626 + gfr3 * dkz
1627 + gfr4 * (qkdiz - qidkz)
1628 + gfr5 * qirz
1629 + gfr6 * qkrz
1630 + gfr7 * (qiqkrz + qkqirz);
1631
1632
1633 final double ttm2rx =
1634 -rr5 * dixdkx
1635 + gfr2 * dixrx
1636 + gfr4 * (dixqkrx + dkxqirx + rxqidkx - 2.0 * qixqkx)
1637 - gfr5 * rxqirx
1638 - gfr7 * (rxqikrx + qkrxqirx);
1639 final double ttm2ry =
1640 -rr5 * dixdky
1641 + gfr2 * dixry
1642 + gfr4 * (dixqkry + dkxqiry + rxqidky - 2.0 * qixqky)
1643 - gfr5 * rxqiry
1644 - gfr7 * (rxqikry + qkrxqiry);
1645 final double ttm2rz =
1646 -rr5 * dixdkz
1647 + gfr2 * dixrz
1648 + gfr4 * (dixqkrz + dkxqirz + rxqidkz - 2.0 * qixqkz)
1649 - gfr5 * rxqirz
1650 - gfr7 * (rxqikrz + qkrxqirz);
1651 final double ttm3rx =
1652 rr5 * dixdkx
1653 + gfr3 * dkxrx
1654 - gfr4 * (dixqkrx + dkxqirx + rxqkdix - 2.0 * qixqkx)
1655 - gfr6 * rxqkrx
1656 - gfr7 * (rxqkirx - qkrxqirx);
1657 final double ttm3ry =
1658 rr5 * dixdky
1659 + gfr3 * dkxry
1660 - gfr4 * (dixqkry + dkxqiry + rxqkdiy - 2.0 * qixqky)
1661 - gfr6 * rxqkry
1662 - gfr7 * (rxqkiry - qkrxqiry);
1663 final double ttm3rz =
1664 rr5 * dixdkz
1665 + gfr3 * dkxrz
1666 - gfr4 * (dixqkrz + dkxqirz + rxqkdiz - 2.0 * qixqkz)
1667 - gfr6 * rxqkrz
1668 - gfr7 * (rxqkirz - qkrxqirz);
1669 ftm2x -= scale1 * ftm2rx;
1670 ftm2y -= scale1 * ftm2ry;
1671 ftm2z -= scale1 * ftm2rz;
1672 ttm2x -= scale1 * ttm2rx;
1673 ttm2y -= scale1 * ttm2ry;
1674 ttm2z -= scale1 * ttm2rz;
1675 ttm3x -= scale1 * ttm3rx;
1676 ttm3y -= scale1 * ttm3ry;
1677 ttm3z -= scale1 * ttm3rz;
1678 }
1679
1680
1681 double prefactor = electric * selfScale * l2 * dlAlpha;
1682 lambdaGrad.add(threadID, i, prefactor * ftm2x, prefactor * ftm2y, prefactor * ftm2z);
1683 lambdaTorque.add(threadID, i, prefactor * ttm2x, prefactor * ttm2y, prefactor * ttm2z);
1684 lxk_local[k] -= prefactor * ftm2x;
1685 lyk_local[k] -= prefactor * ftm2y;
1686 lzk_local[k] -= prefactor * ftm2z;
1687 ltxk_local[k] += prefactor * ttm3x;
1688 ltyk_local[k] += prefactor * ttm3y;
1689 ltzk_local[k] += prefactor * ttm3z;
1690 }
1691
1692 return e;
1693 }
1694
1695
1696
1697
1698
1699
1700 private double polarizationPair(boolean gradientLocal, boolean lambdaTermLocal) {
1701 final double dsc3 = 1.0 - scale3 * scaled;
1702 final double dsc5 = 1.0 - scale5 * scaled;
1703 final double dsc7 = 1.0 - scale7 * scaled;
1704 final double psc3 = 1.0 - scale3 * scalep;
1705 final double psc5 = 1.0 - scale5 * scalep;
1706 final double psc7 = 1.0 - scale7 * scalep;
1707 final double usc3 = 1.0 - scale3;
1708 final double usc5 = 1.0 - scale5;
1709
1710 final double dixukx = diy * ukz - diz * uky;
1711 final double dixuky = diz * ukx - dix * ukz;
1712 final double dixukz = dix * uky - diy * ukx;
1713 final double dkxuix = dky * uiz - dkz * uiy;
1714 final double dkxuiy = dkz * uix - dkx * uiz;
1715 final double dkxuiz = dkx * uiy - dky * uix;
1716 final double dixukpx = diy * pkz - diz * pky;
1717 final double dixukpy = diz * pkx - dix * pkz;
1718 final double dixukpz = dix * pky - diy * pkx;
1719 final double dkxuipx = dky * piz - dkz * piy;
1720 final double dkxuipy = dkz * pix - dkx * piz;
1721 final double dkxuipz = dkx * piy - dky * pix;
1722 final double dixrx = diy * zr - diz * yr;
1723 final double dixry = diz * xr - dix * zr;
1724 final double dixrz = dix * yr - diy * xr;
1725 final double dkxrx = dky * zr - dkz * yr;
1726 final double dkxry = dkz * xr - dkx * zr;
1727 final double dkxrz = dkx * yr - dky * xr;
1728 final double qirx = qixx * xr + qixy * yr + qixz * zr;
1729 final double qiry = qixy * xr + qiyy * yr + qiyz * zr;
1730 final double qirz = qixz * xr + qiyz * yr + qizz * zr;
1731 final double qkrx = qkxx * xr + qkxy * yr + qkxz * zr;
1732 final double qkry = qkxy * xr + qkyy * yr + qkyz * zr;
1733 final double qkrz = qkxz * xr + qkyz * yr + qkzz * zr;
1734 final double rxqirx = yr * qirz - zr * qiry;
1735 final double rxqiry = zr * qirx - xr * qirz;
1736 final double rxqirz = xr * qiry - yr * qirx;
1737 final double rxqkrx = yr * qkrz - zr * qkry;
1738 final double rxqkry = zr * qkrx - xr * qkrz;
1739 final double rxqkrz = xr * qkry - yr * qkrx;
1740 final double qiukx = qixx * ukx + qixy * uky + qixz * ukz;
1741 final double qiuky = qixy * ukx + qiyy * uky + qiyz * ukz;
1742 final double qiukz = qixz * ukx + qiyz * uky + qizz * ukz;
1743 final double qkuix = qkxx * uix + qkxy * uiy + qkxz * uiz;
1744 final double qkuiy = qkxy * uix + qkyy * uiy + qkyz * uiz;
1745 final double qkuiz = qkxz * uix + qkyz * uiy + qkzz * uiz;
1746 final double qiukpx = qixx * pkx + qixy * pky + qixz * pkz;
1747 final double qiukpy = qixy * pkx + qiyy * pky + qiyz * pkz;
1748 final double qiukpz = qixz * pkx + qiyz * pky + qizz * pkz;
1749 final double qkuipx = qkxx * pix + qkxy * piy + qkxz * piz;
1750 final double qkuipy = qkxy * pix + qkyy * piy + qkyz * piz;
1751 final double qkuipz = qkxz * pix + qkyz * piy + qkzz * piz;
1752 final double uixqkrx = uiy * qkrz - uiz * qkry;
1753 final double uixqkry = uiz * qkrx - uix * qkrz;
1754 final double uixqkrz = uix * qkry - uiy * qkrx;
1755 final double ukxqirx = uky * qirz - ukz * qiry;
1756 final double ukxqiry = ukz * qirx - ukx * qirz;
1757 final double ukxqirz = ukx * qiry - uky * qirx;
1758 final double uixqkrpx = piy * qkrz - piz * qkry;
1759 final double uixqkrpy = piz * qkrx - pix * qkrz;
1760 final double uixqkrpz = pix * qkry - piy * qkrx;
1761 final double ukxqirpx = pky * qirz - pkz * qiry;
1762 final double ukxqirpy = pkz * qirx - pkx * qirz;
1763 final double ukxqirpz = pkx * qiry - pky * qirx;
1764 final double rxqiukx = yr * qiukz - zr * qiuky;
1765 final double rxqiuky = zr * qiukx - xr * qiukz;
1766 final double rxqiukz = xr * qiuky - yr * qiukx;
1767 final double rxqkuix = yr * qkuiz - zr * qkuiy;
1768 final double rxqkuiy = zr * qkuix - xr * qkuiz;
1769 final double rxqkuiz = xr * qkuiy - yr * qkuix;
1770 final double rxqiukpx = yr * qiukpz - zr * qiukpy;
1771 final double rxqiukpy = zr * qiukpx - xr * qiukpz;
1772 final double rxqiukpz = xr * qiukpy - yr * qiukpx;
1773 final double rxqkuipx = yr * qkuipz - zr * qkuipy;
1774 final double rxqkuipy = zr * qkuipx - xr * qkuipz;
1775 final double rxqkuipz = xr * qkuipy - yr * qkuipx;
1776
1777
1778 final double sc3 = dix * xr + diy * yr + diz * zr;
1779 final double sc4 = dkx * xr + dky * yr + dkz * zr;
1780 final double sc5 = qirx * xr + qiry * yr + qirz * zr;
1781 final double sc6 = qkrx * xr + qkry * yr + qkrz * zr;
1782
1783
1784 final double sci1 = uix * dkx + uiy * dky + uiz * dkz + dix * ukx + diy * uky + diz * ukz;
1785 final double sci3 = uix * xr + uiy * yr + uiz * zr;
1786 final double sci4 = ukx * xr + uky * yr + ukz * zr;
1787 final double sci7 = qirx * ukx + qiry * uky + qirz * ukz;
1788 final double sci8 = qkrx * uix + qkry * uiy + qkrz * uiz;
1789 final double scip1 = pix * dkx + piy * dky + piz * dkz + dix * pkx + diy * pky + diz * pkz;
1790 final double scip2 = uix * pkx + uiy * pky + uiz * pkz + pix * ukx + piy * uky + piz * ukz;
1791 final double scip3 = pix * xr + piy * yr + piz * zr;
1792 final double scip4 = pkx * xr + pky * yr + pkz * zr;
1793 final double scip7 = qirx * pkx + qiry * pky + qirz * pkz;
1794 final double scip8 = qkrx * pix + qkry * piy + qkrz * piz;
1795
1796
1797 final double gli1 = ck * sci3 - ci * sci4;
1798 final double gli2 = -sc3 * sci4 - sci3 * sc4;
1799 final double gli3 = sci3 * sc6 - sci4 * sc5;
1800 final double gli6 = sci1;
1801 final double gli7 = 2.0 * (sci7 - sci8);
1802 final double glip1 = ck * scip3 - ci * scip4;
1803 final double glip2 = -sc3 * scip4 - scip3 * sc4;
1804 final double glip3 = scip3 * sc6 - scip4 * sc5;
1805 final double glip6 = scip1;
1806 final double glip7 = 2.0 * (scip7 - scip8);
1807
1808
1809 final double ereal = (gli1 + gli6) * bn1 + (gli2 + gli7) * bn2 + gli3 * bn3;
1810 final double efix =
1811 (gli1 + gli6) * rr3 * psc3 + (gli2 + gli7) * rr5 * psc5 + gli3 * rr7 * psc7;
1812 final double e = selfScale * 0.5 * (ereal - efix);
1813
1814
1815
1816
1817 if (!(gradientLocal || lambdaTermLocal)) {
1818 return polarizationScale * e;
1819 }
1820 boolean dorli = false;
1821 if (psc3 != 0.0 || dsc3 != 0.0 || usc3 != 0.0) {
1822 dorli = true;
1823 }
1824
1825
1826 final double gfi1 =
1827 0.5 * bn2 * (gli1 + glip1 + gli6 + glip6)
1828 + 0.5 * bn2 * scip2
1829 + 0.5 * bn3 * (gli2 + glip2 + gli7 + glip7)
1830 - 0.5 * bn3 * (sci3 * scip4 + scip3 * sci4)
1831 + 0.5 * bn4 * (gli3 + glip3);
1832 final double gfi2 = -ck * bn1 + sc4 * bn2 - sc6 * bn3;
1833 final double gfi3 = ci * bn1 + sc3 * bn2 + sc5 * bn3;
1834 final double gfi4 = 2.0 * bn2;
1835 final double gfi5 = bn3 * (sci4 + scip4);
1836 final double gfi6 = -bn3 * (sci3 + scip3);
1837 double ftm2ix =
1838 gfi1 * xr
1839 + 0.5
1840 * (gfi2 * (uix + pix)
1841 + bn2 * (sci4 * pix + scip4 * uix)
1842 + gfi3 * (ukx + pkx)
1843 + bn2 * (sci3 * pkx + scip3 * ukx)
1844 + (sci4 + scip4) * bn2 * dix
1845 + (sci3 + scip3) * bn2 * dkx
1846 + gfi4 * (qkuix + qkuipx - qiukx - qiukpx))
1847 + gfi5 * qirx
1848 + gfi6 * qkrx;
1849 double ftm2iy =
1850 gfi1 * yr
1851 + 0.5
1852 * (gfi2 * (uiy + piy)
1853 + bn2 * (sci4 * piy + scip4 * uiy)
1854 + gfi3 * (uky + pky)
1855 + bn2 * (sci3 * pky + scip3 * uky)
1856 + (sci4 + scip4) * bn2 * diy
1857 + (sci3 + scip3) * bn2 * dky
1858 + gfi4 * (qkuiy + qkuipy - qiuky - qiukpy))
1859 + gfi5 * qiry
1860 + gfi6 * qkry;
1861 double ftm2iz =
1862 gfi1 * zr
1863 + 0.5
1864 * (gfi2 * (uiz + piz)
1865 + bn2 * (sci4 * piz + scip4 * uiz)
1866 + gfi3 * (ukz + pkz)
1867 + bn2 * (sci3 * pkz + scip3 * ukz)
1868 + (sci4 + scip4) * bn2 * diz
1869 + (sci3 + scip3) * bn2 * dkz
1870 + gfi4 * (qkuiz + qkuipz - qiukz - qiukpz))
1871 + gfi5 * qirz
1872 + gfi6 * qkrz;
1873
1874
1875 final double gti2 = 0.5 * bn2 * (sci4 + scip4);
1876 final double gti3 = 0.5 * bn2 * (sci3 + scip3);
1877 final double gti4 = gfi4;
1878 final double gti5 = gfi5;
1879 final double gti6 = gfi6;
1880 double ttm2ix =
1881 -0.5 * bn1 * (dixukx + dixukpx)
1882 + gti2 * dixrx
1883 - gti5 * rxqirx
1884 + 0.5 * gti4 * (ukxqirx + rxqiukx + ukxqirpx + rxqiukpx);
1885 double ttm2iy =
1886 -0.5 * bn1 * (dixuky + dixukpy)
1887 + gti2 * dixry
1888 - gti5 * rxqiry
1889 + 0.5 * gti4 * (ukxqiry + rxqiuky + ukxqirpy + rxqiukpy);
1890 double ttm2iz =
1891 -0.5 * bn1 * (dixukz + dixukpz)
1892 + gti2 * dixrz
1893 - gti5 * rxqirz
1894 + 0.5 * gti4 * (ukxqirz + rxqiukz + ukxqirpz + rxqiukpz);
1895 double ttm3ix =
1896 -0.5 * bn1 * (dkxuix + dkxuipx)
1897 + gti3 * dkxrx
1898 - gti6 * rxqkrx
1899 - 0.5 * gti4 * (uixqkrx + rxqkuix + uixqkrpx + rxqkuipx);
1900 double ttm3iy =
1901 -0.5 * bn1 * (dkxuiy + dkxuipy)
1902 + gti3 * dkxry
1903 - gti6 * rxqkry
1904 - 0.5 * gti4 * (uixqkry + rxqkuiy + uixqkrpy + rxqkuipy);
1905 double ttm3iz =
1906 -0.5 * bn1 * (dkxuiz + dkxuipz)
1907 + gti3 * dkxrz
1908 - gti6 * rxqkrz
1909 - 0.5 * gti4 * (uixqkrz + rxqkuiz + uixqkrpz + rxqkuipz);
1910 double ftm2rix = 0.0;
1911 double ftm2riy = 0.0;
1912 double ftm2riz = 0.0;
1913 double ttm2rix = 0.0;
1914 double ttm2riy = 0.0;
1915 double ttm2riz = 0.0;
1916 double ttm3rix = 0.0;
1917 double ttm3riy = 0.0;
1918 double ttm3riz = 0.0;
1919 if (dorli) {
1920
1921 final double gfri1 =
1922 0.5 * rr5 * ((gli1 + gli6) * psc3 + (glip1 + glip6) * dsc3 + scip2 * usc3)
1923 + 0.5
1924 * rr7
1925 * ((gli7 + gli2) * psc5
1926 + (glip7 + glip2) * dsc5
1927 - (sci3 * scip4 + scip3 * sci4) * usc5)
1928 + 0.5 * rr9 * (gli3 * psc7 + glip3 * dsc7);
1929 final double gfri4 = 2.0 * rr5;
1930 final double gfri5 = rr7 * (sci4 * psc7 + scip4 * dsc7);
1931 final double gfri6 = -rr7 * (sci3 * psc7 + scip3 * dsc7);
1932 ftm2rix =
1933 gfri1 * xr
1934 + 0.5
1935 * (-rr3 * ck * (uix * psc3 + pix * dsc3)
1936 + rr5 * sc4 * (uix * psc5 + pix * dsc5)
1937 - rr7 * sc6 * (uix * psc7 + pix * dsc7))
1938 + (rr3 * ci * (ukx * psc3 + pkx * dsc3)
1939 + rr5 * sc3 * (ukx * psc5 + pkx * dsc5)
1940 + rr7 * sc5 * (ukx * psc7 + pkx * dsc7))
1941 * 0.5
1942 + rr5 * usc5 * (sci4 * pix + scip4 * uix + sci3 * pkx + scip3 * ukx) * 0.5
1943 + 0.5 * (sci4 * psc5 + scip4 * dsc5) * rr5 * dix
1944 + 0.5 * (sci3 * psc5 + scip3 * dsc5) * rr5 * dkx
1945 + 0.5 * gfri4 * ((qkuix - qiukx) * psc5 + (qkuipx - qiukpx) * dsc5)
1946 + gfri5 * qirx
1947 + gfri6 * qkrx;
1948 ftm2riy =
1949 gfri1 * yr
1950 + 0.5
1951 * (-rr3 * ck * (uiy * psc3 + piy * dsc3)
1952 + rr5 * sc4 * (uiy * psc5 + piy * dsc5)
1953 - rr7 * sc6 * (uiy * psc7 + piy * dsc7))
1954 + (rr3 * ci * (uky * psc3 + pky * dsc3)
1955 + rr5 * sc3 * (uky * psc5 + pky * dsc5)
1956 + rr7 * sc5 * (uky * psc7 + pky * dsc7))
1957 * 0.5
1958 + rr5 * usc5 * (sci4 * piy + scip4 * uiy + sci3 * pky + scip3 * uky) * 0.5
1959 + 0.5 * (sci4 * psc5 + scip4 * dsc5) * rr5 * diy
1960 + 0.5 * (sci3 * psc5 + scip3 * dsc5) * rr5 * dky
1961 + 0.5 * gfri4 * ((qkuiy - qiuky) * psc5 + (qkuipy - qiukpy) * dsc5)
1962 + gfri5 * qiry
1963 + gfri6 * qkry;
1964 ftm2riz =
1965 gfri1 * zr
1966 + 0.5
1967 * (-rr3 * ck * (uiz * psc3 + piz * dsc3)
1968 + rr5 * sc4 * (uiz * psc5 + piz * dsc5)
1969 - rr7 * sc6 * (uiz * psc7 + piz * dsc7))
1970 + (rr3 * ci * (ukz * psc3 + pkz * dsc3)
1971 + rr5 * sc3 * (ukz * psc5 + pkz * dsc5)
1972 + rr7 * sc5 * (ukz * psc7 + pkz * dsc7))
1973 * 0.5
1974 + rr5 * usc5 * (sci4 * piz + scip4 * uiz + sci3 * pkz + scip3 * ukz) * 0.5
1975 + 0.5 * (sci4 * psc5 + scip4 * dsc5) * rr5 * diz
1976 + 0.5 * (sci3 * psc5 + scip3 * dsc5) * rr5 * dkz
1977 + 0.5 * gfri4 * ((qkuiz - qiukz) * psc5 + (qkuipz - qiukpz) * dsc5)
1978 + gfri5 * qirz
1979 + gfri6 * qkrz;
1980
1981
1982 final double gtri2 = 0.5 * rr5 * (sci4 * psc5 + scip4 * dsc5);
1983 final double gtri3 = 0.5 * rr5 * (sci3 * psc5 + scip3 * dsc5);
1984 final double gtri4 = gfri4;
1985 final double gtri5 = gfri5;
1986 final double gtri6 = gfri6;
1987 ttm2rix =
1988 -rr3 * (dixukx * psc3 + dixukpx * dsc3) * 0.5
1989 + gtri2 * dixrx
1990 - gtri5 * rxqirx
1991 + gtri4 * ((ukxqirx + rxqiukx) * psc5 + (ukxqirpx + rxqiukpx) * dsc5) * 0.5;
1992 ttm2riy =
1993 -rr3 * (dixuky * psc3 + dixukpy * dsc3) * 0.5
1994 + gtri2 * dixry
1995 - gtri5 * rxqiry
1996 + gtri4 * ((ukxqiry + rxqiuky) * psc5 + (ukxqirpy + rxqiukpy) * dsc5) * 0.5;
1997 ttm2riz =
1998 -rr3 * (dixukz * psc3 + dixukpz * dsc3) * 0.5
1999 + gtri2 * dixrz
2000 - gtri5 * rxqirz
2001 + gtri4 * ((ukxqirz + rxqiukz) * psc5 + (ukxqirpz + rxqiukpz) * dsc5) * 0.5;
2002 ttm3rix =
2003 -rr3 * (dkxuix * psc3 + dkxuipx * dsc3) * 0.5
2004 + gtri3 * dkxrx
2005 - gtri6 * rxqkrx
2006 - gtri4 * ((uixqkrx + rxqkuix) * psc5 + (uixqkrpx + rxqkuipx) * dsc5) * 0.5;
2007 ttm3riy =
2008 -rr3 * (dkxuiy * psc3 + dkxuipy * dsc3) * 0.5
2009 + gtri3 * dkxry
2010 - gtri6 * rxqkry
2011 - gtri4 * ((uixqkry + rxqkuiy) * psc5 + (uixqkrpy + rxqkuipy) * dsc5) * 0.5;
2012 ttm3riz =
2013 -rr3 * (dkxuiz * psc3 + dkxuipz * dsc3) * 0.5
2014 + gtri3 * dkxrz
2015 - gtri6 * rxqkrz
2016 - gtri4 * ((uixqkrz + rxqkuiz) * psc5 + (uixqkrpz + rxqkuipz) * dsc5) * 0.5;
2017 }
2018
2019
2020 double temp3 = 0.5 * rr3 * ((gli1 + gli6) * scalep + (glip1 + glip6) * scaled);
2021 double temp5 = 0.5 * rr5 * ((gli2 + gli7) * scalep + (glip2 + glip7) * scaled);
2022 final double temp7 = 0.5 * rr7 * (gli3 * scalep + glip3 * scaled);
2023 final double fridmpx = temp3 * ddsc3x + temp5 * ddsc5x + temp7 * ddsc7x;
2024 final double fridmpy = temp3 * ddsc3y + temp5 * ddsc5y + temp7 * ddsc7y;
2025 final double fridmpz = temp3 * ddsc3z + temp5 * ddsc5z + temp7 * ddsc7z;
2026
2027
2028 temp3 = 0.5 * rr3 * scip2;
2029 temp5 = -0.5 * rr5 * (sci3 * scip4 + scip3 * sci4);
2030 final double findmpx = temp3 * ddsc3x + temp5 * ddsc5x;
2031 final double findmpy = temp3 * ddsc3y + temp5 * ddsc5y;
2032 final double findmpz = temp3 * ddsc3z + temp5 * ddsc5z;
2033
2034
2035
2036
2037
2038
2039 ftm2ix = ftm2ix - fridmpx - findmpx;
2040 ftm2iy = ftm2iy - fridmpy - findmpy;
2041 ftm2iz = ftm2iz - fridmpz - findmpz;
2042
2043
2044 if (polarization == Polarization.DIRECT) {
2045 final double gfd = 0.5 * (bn2 * scip2 - bn3 * (scip3 * sci4 + sci3 * scip4));
2046 final double gfdr = 0.5 * (rr5 * scip2 * usc3 - rr7 * (scip3 * sci4 + sci3 * scip4) * usc5);
2047 ftm2ix = ftm2ix - gfd * xr - 0.5 * bn2 * (sci4 * pix + scip4 * uix + sci3 * pkx + scip3 * ukx);
2048 ftm2iy = ftm2iy - gfd * yr - 0.5 * bn2 * (sci4 * piy + scip4 * uiy + sci3 * pky + scip3 * uky);
2049 ftm2iz = ftm2iz - gfd * zr - 0.5 * bn2 * (sci4 * piz + scip4 * uiz + sci3 * pkz + scip3 * ukz);
2050 final double fdirx = gfdr * xr + 0.5 * usc5 * rr5 * (sci4 * pix + scip4 * uix + sci3 * pkx + scip3 * ukx);
2051 final double fdiry = gfdr * yr + 0.5 * usc5 * rr5 * (sci4 * piy + scip4 * uiy + sci3 * pky + scip3 * uky);
2052 final double fdirz = gfdr * zr + 0.5 * usc5 * rr5 * (sci4 * piz + scip4 * uiz + sci3 * pkz + scip3 * ukz);
2053 ftm2ix = ftm2ix + fdirx + findmpx;
2054 ftm2iy = ftm2iy + fdiry + findmpy;
2055 ftm2iz = ftm2iz + fdirz + findmpz;
2056 }
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143 ftm2ix = ftm2ix - ftm2rix;
2144 ftm2iy = ftm2iy - ftm2riy;
2145 ftm2iz = ftm2iz - ftm2riz;
2146 ttm2ix = ttm2ix - ttm2rix;
2147 ttm2iy = ttm2iy - ttm2riy;
2148 ttm2iz = ttm2iz - ttm2riz;
2149 ttm3ix = ttm3ix - ttm3rix;
2150 ttm3iy = ttm3iy - ttm3riy;
2151 ttm3iz = ttm3iz - ttm3riz;
2152
2153 double scalar = electric * polarizationScale * selfScale;
2154
2155 grad.add(threadID, i, scalar * ftm2ix, scalar * ftm2iy, scalar * ftm2iz);
2156 torque.add(threadID, i, scalar * ttm2ix, scalar * ttm2iy, scalar * ttm2iz);
2157 gxk_local[k] -= scalar * ftm2ix;
2158 gyk_local[k] -= scalar * ftm2iy;
2159 gzk_local[k] -= scalar * ftm2iz;
2160 txk_local[k] += scalar * ttm3ix;
2161 tyk_local[k] += scalar * ttm3iy;
2162 tzk_local[k] += scalar * ttm3iz;
2163 if (lambdaTermLocal) {
2164 dUdL += dEdLSign * dlPowPol * e;
2165 d2UdL2 += dEdLSign * d2lPowPol * e;
2166 scalar = electric * dEdLSign * dlPowPol * selfScale;
2167 lambdaGrad.add(threadID, i, scalar * ftm2ix, scalar * ftm2iy, scalar * ftm2iz);
2168 lambdaTorque.add(threadID, i, scalar * ttm2ix, scalar * ttm2iy, scalar * ttm2iz);
2169 lxk_local[k] -= scalar * ftm2ix;
2170 lyk_local[k] -= scalar * ftm2iy;
2171 lzk_local[k] -= scalar * ftm2iz;
2172 ltxk_local[k] += scalar * ttm3ix;
2173 ltyk_local[k] += scalar * ttm3iy;
2174 ltzk_local[k] += scalar * ttm3iz;
2175 }
2176 return polarizationScale * e;
2177 }
2178
2179 private void setMultipoleI(double[] globalMultipolei) {
2180 ci = globalMultipolei[t000];
2181 dix = globalMultipolei[t100];
2182 diy = globalMultipolei[t010];
2183 diz = globalMultipolei[t001];
2184 qixx = globalMultipolei[t200] * oneThird;
2185 qiyy = globalMultipolei[t020] * oneThird;
2186 qizz = globalMultipolei[t002] * oneThird;
2187 qixy = globalMultipolei[t110] * oneThird;
2188 qixz = globalMultipolei[t101] * oneThird;
2189 qiyz = globalMultipolei[t011] * oneThird;
2190 }
2191
2192 private void setMultipoleK(double[] globalMultipolek) {
2193 ck = globalMultipolek[t000];
2194 dkx = globalMultipolek[t100];
2195 dky = globalMultipolek[t010];
2196 dkz = globalMultipolek[t001];
2197 qkxx = globalMultipolek[t200] * oneThird;
2198 qkyy = globalMultipolek[t020] * oneThird;
2199 qkzz = globalMultipolek[t002] * oneThird;
2200 qkxy = globalMultipolek[t110] * oneThird;
2201 qkxz = globalMultipolek[t101] * oneThird;
2202 qkyz = globalMultipolek[t011] * oneThird;
2203 }
2204
2205 private void setInducedI(double[] inducedDipolei) {
2206 uix = inducedDipolei[0];
2207 uiy = inducedDipolei[1];
2208 uiz = inducedDipolei[2];
2209 }
2210
2211 private void setInducedK(double[] inducedDipolek) {
2212 ukx = inducedDipolek[0];
2213 uky = inducedDipolek[1];
2214 ukz = inducedDipolek[2];
2215 }
2216
2217 private void setInducedpI(double[] inducedDipolepi) {
2218 pix = inducedDipolepi[0];
2219 piy = inducedDipolepi[1];
2220 piz = inducedDipolepi[2];
2221 }
2222
2223 private void setInducedpK(double[] inducedDipolepk) {
2224 pkx = inducedDipolepk[0];
2225 pky = inducedDipolepk[1];
2226 pkz = inducedDipolepk[2];
2227 }
2228
2229 }
2230
2231
2232
2233
2234
2235 private class FixedChargeEnergyLoop extends IntegerForLoop {
2236
2237 private final double[] dx_local;
2238 private final double[][] rot_local;
2239 private double ci;
2240 private double ck;
2241 private double xr, yr, zr;
2242 private double bn0, bn1, bn2;
2243 private double rr1, rr3, rr5;
2244 private double scale;
2245 private double l2;
2246 private boolean soft;
2247 private double selfScale;
2248 private double permanentEnergy;
2249 private double inducedEnergy;
2250 private double dUdL, d2UdL2;
2251 private int i, k, iSymm, count;
2252 private double[] gxk_local, gyk_local, gzk_local;
2253 private double[] lxk_local, lyk_local, lzk_local;
2254 private double[] masking_local;
2255 private int threadID;
2256
2257 FixedChargeEnergyLoop() {
2258 super();
2259 dx_local = new double[3];
2260 rot_local = new double[3][3];
2261 }
2262
2263 @Override
2264 public void finish() {
2265 sharedInteractions.addAndGet(count);
2266 if (lambdaTerm) {
2267 shareddEdLambda.addAndGet(dUdL * electric);
2268 sharedd2EdLambda2.addAndGet(d2UdL2 * electric);
2269 }
2270 realSpaceEnergyTime[getThreadIndex()] += System.nanoTime();
2271 }
2272
2273 public int getCount() {
2274 return count;
2275 }
2276
2277 @Override
2278 public void run(int lb, int ub) {
2279 List<SymOp> symOps = crystal.spaceGroup.symOps;
2280 int nSymm = symOps.size();
2281 int nAtoms = atoms.length;
2282 for (iSymm = 0; iSymm < nSymm; iSymm++) {
2283 SymOp symOp = symOps.get(iSymm);
2284 if (gradient) {
2285 fill(gxk_local, 0.0);
2286 fill(gyk_local, 0.0);
2287 fill(gzk_local, 0.0);
2288 }
2289 if (lambdaTerm) {
2290 fill(lxk_local, 0.0);
2291 fill(lyk_local, 0.0);
2292 fill(lzk_local, 0.0);
2293 }
2294 realSpaceChunk(lb, ub);
2295 if (gradient) {
2296
2297 if (iSymm != 0) {
2298 crystal.applyTransSymRot(nAtoms, gxk_local, gyk_local, gzk_local, gxk_local, gyk_local, gzk_local, symOp, rot_local);
2299 }
2300
2301 for (int j = 0; j < nAtoms; j++) {
2302 grad.add(threadID, j, gxk_local[j], gyk_local[j], gzk_local[j]);
2303 }
2304 }
2305 if (lambdaTerm) {
2306
2307 if (iSymm != 0) {
2308 crystal.applyTransSymRot(
2309 nAtoms, lxk_local, lyk_local, lzk_local, lxk_local, lyk_local, lzk_local, symOp,
2310 rot_local);
2311 }
2312
2313 for (int j = 0; j < nAtoms; j++) {
2314 lambdaGrad.add(threadID, j, lxk_local[j], lyk_local[j], lzk_local[j]);
2315 }
2316 }
2317 }
2318 }
2319
2320 @Override
2321 public IntegerSchedule schedule() {
2322 return realSpaceSchedule;
2323 }
2324
2325 @Override
2326 public void start() {
2327 init();
2328 threadID = getThreadIndex();
2329 realSpaceEnergyTime[threadID] -= System.nanoTime();
2330 permanentEnergy = 0.0;
2331 inducedEnergy = 0.0;
2332 count = 0;
2333 if (lambdaTerm) {
2334 dUdL = 0.0;
2335 d2UdL2 = 0.0;
2336 }
2337 }
2338
2339 private void init() {
2340 int nAtoms = atoms.length;
2341 if (masking_local == null || masking_local.length < nAtoms) {
2342 gxk_local = new double[nAtoms];
2343 gyk_local = new double[nAtoms];
2344 gzk_local = new double[nAtoms];
2345 lxk_local = new double[nAtoms];
2346 lyk_local = new double[nAtoms];
2347 lzk_local = new double[nAtoms];
2348 masking_local = new double[nAtoms];
2349 fill(masking_local, 1.0);
2350 }
2351 }
2352
2353
2354
2355
2356
2357
2358
2359 private void realSpaceChunk(final int lb, final int ub) {
2360 final double[] x = coordinates[0][0];
2361 final double[] y = coordinates[0][1];
2362 final double[] z = coordinates[0][2];
2363 final double[][] mpole = globalMultipole[0];
2364 final int[][] lists = realSpaceLists[iSymm];
2365 final double[] neighborX = coordinates[iSymm][0];
2366 final double[] neighborY = coordinates[iSymm][1];
2367 final double[] neighborZ = coordinates[iSymm][2];
2368 final double[][] neighborMultipole = globalMultipole[iSymm];
2369 for (i = lb; i <= ub; i++) {
2370 if (!use[i]) {
2371 continue;
2372 }
2373 final int moleculei = molecule[i];
2374 if (iSymm == 0) {
2375 applyMask(i, null, masking_local);
2376 }
2377 final double xi = x[i];
2378 final double yi = y[i];
2379 final double zi = z[i];
2380 final double[] globalMultipolei = mpole[i];
2381 setMultipoleI(globalMultipolei);
2382 final boolean softi = isSoft[i];
2383 final int[] list = lists[i];
2384 final int npair = realSpaceCounts[iSymm][i];
2385 for (int j = 0; j < npair; j++) {
2386 k = list[j];
2387 if (!use[k]) {
2388 continue;
2389 }
2390 boolean sameMolecule = (moleculei == molecule[k]);
2391 if (lambdaMode == LambdaMode.VAPOR) {
2392 if ((intermolecularSoftcore && !sameMolecule)
2393 || (intramolecularSoftcore && sameMolecule)) {
2394 continue;
2395 }
2396 }
2397 selfScale = 1.0;
2398 if (i == k) {
2399 selfScale = 0.5;
2400 }
2401 double beta = 0.0;
2402 l2 = 1.0;
2403 soft = (softi || isSoft[k]);
2404 if (soft && doPermanentRealSpace) {
2405 beta = lAlpha;
2406 l2 = permanentScale;
2407 } else if (nnTerm) {
2408 l2 = permanentScale;
2409 }
2410 final double xk = neighborX[k];
2411 final double yk = neighborY[k];
2412 final double zk = neighborZ[k];
2413 dx_local[0] = xk - xi;
2414 dx_local[1] = yk - yi;
2415 dx_local[2] = zk - zi;
2416 double r2 = crystal.image(dx_local);
2417 xr = dx_local[0];
2418 yr = dx_local[1];
2419 zr = dx_local[2];
2420 final double[] globalMultipolek = neighborMultipole[k];
2421 setMultipoleK(globalMultipolek);
2422 scale = masking_local[k];
2423 double r = sqrt(r2 + beta);
2424 double ralpha = aewald * r;
2425 double exp2a = exp(-ralpha * ralpha);
2426 rr1 = 1.0 / r;
2427 double rr2 = rr1 * rr1;
2428 bn0 = erfc(ralpha) * rr1;
2429 bn1 = (bn0 + an0 * exp2a) * rr2;
2430 bn2 = (3.0 * bn1 + an1 * exp2a) * rr2;
2431 rr3 = rr1 * rr2;
2432 rr5 = 3.0 * rr3 * rr2;
2433 if (doPermanentRealSpace) {
2434 double ei = permanentPair(gradient, lambdaTerm);
2435 if (isNaN(ei) || isInfinite(ei)) {
2436 String message = format(" %s\n %s\n %s\n The permanent multipole energy between "
2437 + "atoms %d and %d (%d) is %16.8f at %16.8f A.",
2438 crystal.getUnitCell().toString(), atoms[i].toString(), atoms[k].toString(),
2439 i, k, iSymm, ei, r);
2440 throw new EnergyException(message);
2441 }
2442 if (ei != 0.0) {
2443 permanentEnergy += ei;
2444 count++;
2445 }
2446 if (esvTerm) {
2447 if (extendedSystem.isTitrating(i)) {
2448 double titrdUdL = 0.0;
2449 double tautdUdL = 0.0;
2450 final double[][] titrMpole = titrationMultipole[0];
2451 final double[] titrMultipolei = titrMpole[i];
2452 setMultipoleI(titrMultipolei);
2453 titrdUdL = electric * permanentPair(false, false);
2454 if (extendedSystem.isTautomerizing(i)) {
2455 final double[][] tautMpole = tautomerMultipole[0];
2456 final double[] tautMultipolei = tautMpole[i];
2457 setMultipoleI(tautMultipolei);
2458 tautdUdL = electric * permanentPair(false, false);
2459 }
2460 extendedSystem.addPermElecDeriv(i, titrdUdL, tautdUdL);
2461
2462 setMultipoleI(globalMultipolei);
2463 }
2464 if (extendedSystem.isTitrating(k)) {
2465 double titrdUdL = 0.0;
2466 double tautdUdL = 0.0;
2467 final double[][] titrNeighborMpole = titrationMultipole[iSymm];
2468 final double[] titrMultipolek = titrNeighborMpole[k];
2469 setMultipoleK(titrMultipolek);
2470 titrdUdL = electric * permanentPair(false, false);
2471 if (extendedSystem.isTautomerizing(k)) {
2472 final double[][] tautNeighborMpole = tautomerMultipole[iSymm];
2473 final double[] tautMultipolek = tautNeighborMpole[k];
2474 setMultipoleK(tautMultipolek);
2475 tautdUdL = electric * permanentPair(false, false);
2476 }
2477 extendedSystem.addPermElecDeriv(k, titrdUdL, tautdUdL);
2478
2479 setMultipoleK(globalMultipolek);
2480 }
2481 }
2482 }
2483 }
2484 if (iSymm == 0) {
2485 removeMask(i, null, masking_local);
2486 }
2487 }
2488 }
2489
2490
2491
2492
2493
2494
2495 private double permanentPair(boolean gradientLocal, boolean lambdaTermLocal) {
2496
2497
2498 final double gl0 = ci * ck;
2499
2500
2501 final double scale1 = 1.0 - scale;
2502 final double ereal = gl0 * bn0;
2503 final double efix = scale1 * (gl0 * rr1);
2504 final double e = selfScale * l2 * (ereal - efix);
2505 if (gradientLocal) {
2506 final double gf1 = bn1 * gl0;
2507
2508 double ftm2x = gf1 * xr;
2509 double ftm2y = gf1 * yr;
2510 double ftm2z = gf1 * zr;
2511
2512
2513 if (scale1 != 0.0) {
2514 final double gfr1 = rr3 * gl0;
2515
2516 final double ftm2rx = gfr1 * xr;
2517 final double ftm2ry = gfr1 * yr;
2518 final double ftm2rz = gfr1 * zr;
2519 ftm2x -= scale1 * ftm2rx;
2520 ftm2y -= scale1 * ftm2ry;
2521 ftm2z -= scale1 * ftm2rz;
2522 }
2523 double prefactor = electric * selfScale * l2;
2524 grad.add(threadID, i, prefactor * ftm2x, prefactor * ftm2y, prefactor * ftm2z);
2525 gxk_local[k] -= prefactor * ftm2x;
2526 gyk_local[k] -= prefactor * ftm2y;
2527 gzk_local[k] -= prefactor * ftm2z;
2528
2529
2530 if (lambdaTerm && soft) {
2531 prefactor = electric * selfScale * dEdLSign * dlPowPerm;
2532 lambdaGrad.add(threadID, i, prefactor * ftm2x, prefactor * ftm2y, prefactor * ftm2z);
2533 lxk_local[k] -= prefactor * ftm2x;
2534 lyk_local[k] -= prefactor * ftm2y;
2535 lzk_local[k] -= prefactor * ftm2z;
2536 }
2537 }
2538
2539 if (lambdaTermLocal && soft) {
2540 double dRealdL = gl0 * bn1;
2541 double d2RealdL2 = gl0 * bn2;
2542
2543 dUdL += selfScale * (dEdLSign * dlPowPerm * ereal + l2 * dlAlpha * dRealdL);
2544 d2UdL2 += selfScale * (dEdLSign * (d2lPowPerm * ereal
2545 + dlPowPerm * dlAlpha * dRealdL
2546 + dlPowPerm * dlAlpha * dRealdL)
2547 + l2 * d2lAlpha * dRealdL
2548 + l2 * dlAlpha * dlAlpha * d2RealdL2);
2549
2550 double dFixdL = gl0 * rr3;
2551 double d2FixdL2 = gl0 * rr5;
2552 dFixdL *= scale1;
2553 d2FixdL2 *= scale1;
2554 dUdL -= selfScale * (dEdLSign * dlPowPerm * efix + l2 * dlAlpha * dFixdL);
2555 d2UdL2 -= selfScale * (dEdLSign * (d2lPowPerm * efix
2556 + dlPowPerm * dlAlpha * dFixdL
2557 + dlPowPerm * dlAlpha * dFixdL)
2558 + l2 * d2lAlpha * dFixdL
2559 + l2 * dlAlpha * dlAlpha * d2FixdL2);
2560
2561
2562 final double gf1 = bn2 * gl0;
2563
2564 double ftm2x = gf1 * xr;
2565 double ftm2y = gf1 * yr;
2566 double ftm2z = gf1 * zr;
2567
2568
2569 if (scale1 != 0.0) {
2570 final double gfr1 = rr5 * gl0;
2571
2572 final double ftm2rx = gfr1 * xr;
2573 final double ftm2ry = gfr1 * yr;
2574 final double ftm2rz = gfr1 * zr;
2575 ftm2x -= scale1 * ftm2rx;
2576 ftm2y -= scale1 * ftm2ry;
2577 ftm2z -= scale1 * ftm2rz;
2578 }
2579
2580
2581 double prefactor = electric * selfScale * l2 * dlAlpha;
2582 lambdaGrad.add(threadID, i, prefactor * ftm2x, prefactor * ftm2y, prefactor * ftm2z);
2583 lxk_local[k] -= prefactor * ftm2x;
2584 lyk_local[k] -= prefactor * ftm2y;
2585 lzk_local[k] -= prefactor * ftm2z;
2586 }
2587 return e;
2588 }
2589
2590 private void setMultipoleI(double[] globalMultipolei) {
2591 ci = globalMultipolei[t000];
2592 }
2593
2594 private void setMultipoleK(double[] globalMultipolek) {
2595 ck = globalMultipolek[t000];
2596 }
2597
2598 }
2599
2600 }