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