1 // ******************************************************************************
2 //
3 // Title: Force Field X.
4 // Description: Force Field X - Software for Molecular Biophysics.
5 // Copyright: Copyright (c) Michael J. Schnieders 2001-2025.
6 //
7 // This file is part of Force Field X.
8 //
9 // Force Field X is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License version 3 as published by
11 // the Free Software Foundation.
12 //
13 // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 // details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20 // Place, Suite 330, Boston, MA 02111-1307 USA
21 //
22 // Linking this library statically or dynamically with other modules is making a
23 // combined work based on this library. Thus, the terms and conditions of the
24 // GNU General Public License cover the whole combination.
25 //
26 // As a special exception, the copyright holders of this library give you
27 // permission to link this library with independent modules to produce an
28 // executable, regardless of the license terms of these independent modules, and
29 // to copy and distribute the resulting executable under terms of your choice,
30 // provided that you also meet, for each linked independent module, the terms
31 // and conditions of the license of that module. An independent module is a
32 // module which is not derived from or based on this library. If you modify this
33 // library, you may extend this exception to your version of the library, but
34 // you are not obligated to do so. If you do not wish to do so, delete this
35 // exception statement from your version.
36 //
37 // ******************************************************************************
38 package ffx.potential.nonbonded.implicit;
39
40 import edu.rit.pj.IntegerForLoop;
41 import edu.rit.pj.ParallelRegion;
42 import edu.rit.pj.reduction.SharedDouble;
43 import ffx.crystal.Crystal;
44 import ffx.numerics.atomic.AtomicDoubleArray3D;
45 import ffx.potential.bonded.Atom;
46 import ffx.potential.parameters.ForceField;
47 import ffx.potential.parameters.VDWType;
48 import ffx.potential.parameters.VDWType.EPSILON_RULE;
49 import ffx.potential.parameters.VDWType.RADIUS_RULE;
50
51 import java.util.logging.Level;
52 import java.util.logging.Logger;
53
54 import static ffx.potential.nonbonded.VanDerWaalsForm.getCombinedEps;
55 import static ffx.potential.nonbonded.VanDerWaalsForm.getCombinedRadius;
56 import static org.apache.commons.math3.util.FastMath.PI;
57 import static org.apache.commons.math3.util.FastMath.max;
58 import static org.apache.commons.math3.util.FastMath.min;
59 import static org.apache.commons.math3.util.FastMath.pow;
60 import static org.apache.commons.math3.util.FastMath.sqrt;
61
62 /**
63 * Parallel calculation of continuum dispersion energy via pairwise descreening.
64 *
65 * @author Michael J. Schnieders
66 * @since 1.0
67 */
68 public class DispersionRegion extends ParallelRegion {
69
70 /** The dispersion integral begins for each atom at: Rmin_ij + DISPERSION_OFFSET */
71 public static final double DEFAULT_DISPERSION_OFFSET = 1.056;
72 /** Each solute atom blocks dispersion interactions with solvent: Rmin + SOLUTE_OFFSET */
73 public static final double DEFAULT_SOLUTE_OFFSET = 0.0;
74
75 private static final Logger logger = Logger.getLogger(DispersionRegion.class.getName());
76 /** The dispersion integral HCT overlap scale factor. */
77 private static final double DEFAULT_DISP_OVERLAP_FACTOR = 0.75;
78 /**
79 * Conversion between solute-solvent dispersion enthalpy and solute-solvent dispersion free
80 * energy.
81 */
82 private static final double SLEVY = 1.0;
83 /** Number density of water (water per A^3). */
84 private static final double AWATER = 0.033428;
85 /** AMOEBA '03 Water oxygen epsilon. */
86 private static final double EPSO = 0.1100;
87 /** AMOEBA '03 Water hydrogen epsilon. */
88 private static final double EPSH = 0.0135;
89 /** AMOEBA '03 Water oxygen Rmin (A). */
90 private static final double RMINO = 1.7025;
91 /** AMOEBA '03 Water hydrogen Rmin (A). */
92 private static final double RMINH = 1.3275;
93 /** AMOEBA epsilon rule. */
94 private static final EPSILON_RULE epsilonRule = VDWType.EPSILON_RULE.HHG;
95 /** AMOEBA radius rule. */
96 private static final RADIUS_RULE radiusRule = VDWType.RADIUS_RULE.CUBIC_MEAN;
97
98 private final DispersionLoop[] dispersionLoop;
99 private final SharedDouble sharedDispersion;
100 /** An ordered array of atoms in the system. */
101 protected Atom[] atoms;
102 /** Periodic boundary conditions and symmetry. */
103 private Crystal crystal;
104 /** Flag to indicate if an atom should be included. */
105 private boolean[] use = null;
106 /** Neighbor lists for each atom and symmetry operator. */
107 private int[][][] neighborLists;
108 /** Cartesian coordinates of each atom. */
109 private double[] x, y, z;
110 /** GK cut-off distance squared. */
111 private double cut2;
112 /** Boolean flag to indicate GK will be scaled by the lambda state variable. */
113 private boolean gradient = false;
114 /** Gradient array for each thread. */
115 private AtomicDoubleArray3D grad;
116 /** Where the dispersion integral begins for each atom (A): Rmin + dispersionOffset */
117 private double dispersionOffest;
118 /**
119 * Each solute atom blocks dispersion interactions with solvent with this radius (A): Rmin +
120 * soluteOffset
121 */
122 private double soluteOffset;
123 /** The dispersion integral HCT overlap scale factor (unitless). */
124 private double dispersionOverlapFactor;
125
126 /**
127 * DispersionRegion constructor.
128 *
129 * @param nt Number of threads.
130 * @param atoms Atom array.
131 * @param forceField ForceField in use.
132 */
133 public DispersionRegion(int nt, Atom[] atoms, ForceField forceField) {
134 dispersionLoop = new DispersionLoop[nt];
135 for (int i = 0; i < nt; i++) {
136 dispersionLoop[i] = new DispersionLoop();
137 }
138 sharedDispersion = new SharedDouble();
139
140 dispersionOffest = forceField.getDouble("DISPERSION_OFFSET", DEFAULT_DISPERSION_OFFSET);
141 soluteOffset = forceField.getDouble("SOLUTE_OFFSET", DEFAULT_SOLUTE_OFFSET);
142 dispersionOverlapFactor =
143 forceField.getDouble("DISP_OVERLAP_FACTOR", DEFAULT_DISP_OVERLAP_FACTOR);
144
145 allocate(atoms);
146 }
147
148 /**
149 * Compute a Buffered-14-7 tail correction.
150 *
151 * @param r0 The separation distance where the intregal begins.
152 * @param eps The mixed eps value.
153 * @param rmin The mixed rmin value.
154 * @return The tail correction.
155 */
156 private static double tailCorrection(double r0, double eps, double rmin) {
157 if (r0 < rmin) {
158 double r03 = r0 * r0 * r0;
159 double rmin3 = rmin * rmin * rmin;
160 return -eps * 4.0 * PI * (rmin3 - r03) / 3.0 - eps * PI * 18.0 * rmin3 / 11.0;
161 } else {
162 double ri2 = r0 * r0;
163 double ri4 = ri2 * ri2;
164 double ri7 = r0 * ri2 * ri4;
165 double ri11 = ri7 * ri4;
166 double rmin2 = rmin * rmin;
167 double rmin4 = rmin2 * rmin2;
168 double rmin7 = rmin * rmin2 * rmin4;
169 return 2.0 * PI * eps * rmin7 * (2.0 * rmin7 - 11.0 * ri7) / (11.0 * ri11);
170 }
171 }
172
173 /**
174 * Allocate storage given the Atom array.
175 *
176 * @param atoms Atom array in use.
177 */
178 public void allocate(Atom[] atoms) {
179 this.atoms = atoms;
180 }
181
182 /**
183 * The dispersion integral begins offset from the vdW radius.
184 *
185 * @param dispersionOffest The dispersion integral offset.
186 */
187 public void setDispersionOffest(double dispersionOffest) {
188 this.dispersionOffest = dispersionOffest;
189 }
190
191 /**
192 * The dispersion integral begins offset from the vdW radius.
193 *
194 * @return the dispersion integral offset.
195 */
196 public double getDispersionOffset() {
197 return dispersionOffest;
198 }
199
200 public double getDispersionOverlapFactor() {
201 return dispersionOverlapFactor;
202 }
203
204 /**
205 * Set the dispersion overlap HCT scale factor.
206 *
207 * @param dispersionOverlapFactor The dispersion integral HCT scale factor.
208 */
209 public void setDispersionOverlapFactor(double dispersionOverlapFactor) {
210 this.dispersionOverlapFactor = dispersionOverlapFactor;
211 }
212
213 public double getEnergy() {
214 return sharedDispersion.get();
215 }
216
217 public double getSoluteOffset() {
218 return soluteOffset;
219 }
220
221 public void setSoluteOffset(double soluteOffset) {
222 this.soluteOffset = soluteOffset;
223 }
224
225 /**
226 * Initialize the DispersionRegion for energy calculation.
227 *
228 * @param atoms Atom array.
229 * @param crystal Crystal for periodic boundary conditions.
230 * @param use Flag to indicate an atom is to be used.
231 * @param neighborLists Neighbor-list for each atom.
232 * @param x X-coordinate array.
233 * @param y Y-coordinate array.
234 * @param z Z-coordinate array.
235 * @param cut2 The cut-off distance squared.
236 * @param gradient If true, compute the gradient.
237 * @param grad Array to store the gradient.
238 */
239 public void init(
240 Atom[] atoms,
241 Crystal crystal,
242 boolean[] use,
243 int[][][] neighborLists,
244 double[] x,
245 double[] y,
246 double[] z,
247 double cut2,
248 boolean gradient,
249 AtomicDoubleArray3D grad) {
250 this.atoms = atoms;
251 this.crystal = crystal;
252 this.use = use;
253 this.neighborLists = neighborLists;
254 this.x = x;
255 this.y = y;
256 this.z = z;
257 this.cut2 = cut2;
258 this.gradient = gradient;
259 this.grad = grad;
260 }
261
262 /** {@inheritDoc} */
263 @Override
264 public void run() {
265 try {
266 int nAtoms = atoms.length;
267 execute(0, nAtoms - 1, dispersionLoop[getThreadIndex()]);
268 } catch (Exception e) {
269 String message =
270 "Fatal exception computing Dispersion energy in thread " + getThreadIndex() + "\n";
271 logger.log(Level.SEVERE, message, e);
272 }
273 }
274
275 /** {@inheritDoc} */
276 @Override
277 public void start() {
278 sharedDispersion.set(0.0);
279 }
280
281 /**
282 * Compute Dispersion energy for a range of atoms via pairwise descreening.
283 *
284 * @since 1.0
285 */
286 private class DispersionLoop extends IntegerForLoop {
287
288 private final double[] dx_local;
289 private double edisp;
290 private double r, r2, r3;
291 private double xr, yr, zr;
292 private int threadID;
293
294 DispersionLoop() {
295 dx_local = new double[3];
296 }
297
298 @Override
299 public void finish() {
300 sharedDispersion.addAndGet(edisp);
301 }
302
303 @Override
304 public void run(int lb, int ub) {
305 for (int i = lb; i <= ub; i++) {
306 if (!use[i]) {
307 continue;
308 }
309
310 // Compute the limit of atom alone in solvent.
311 VDWType type = atoms[i].getVDWType();
312 double epsi = type.wellDepth;
313 double rmini = type.radius / 2.0;
314 double cDisp = 0.0;
315 if (rmini > 0.0 && epsi > 0.0) {
316 double emixo = getCombinedEps(EPSO, epsi, RMINO, rmini, epsilonRule);
317 double rmixo = getCombinedRadius(RMINO, rmini, radiusRule);
318 // Start of integration of dispersion for atom i with water oxygen.
319 double riO = rmixo / 2.0 + dispersionOffest;
320 cDisp = tailCorrection(riO, emixo, rmixo);
321 double emixh = getCombinedEps(EPSH, epsi, RMINH, rmini, epsilonRule);
322 double rmixh = getCombinedRadius(RMINH, rmini, radiusRule);
323 // Start of integration of dispersion for atom i with water hydrogen.
324 double riH = rmixh / 2.0 + dispersionOffest;
325 cDisp += 2.0 * tailCorrection(riH, emixh, rmixh);
326 cDisp = SLEVY * AWATER * cDisp;
327 }
328
329 edisp += cDisp;
330
331 // Now descreen over neighbors.
332 double sum = 0.0;
333 final double xi = x[i];
334 final double yi = y[i];
335 final double zi = z[i];
336 int[] list = neighborLists[0][i];
337 for (int k : list) {
338 if (!use[k] || i == k) {
339 continue;
340 }
341 if (atoms[k].getVDWType().radius > 0.0) {
342 dx_local[0] = xi - x[k];
343 dx_local[1] = yi - y[k];
344 dx_local[2] = zi - z[k];
345 r2 = crystal.image(dx_local);
346 if (r2 > cut2) {
347 continue;
348 }
349 xr = dx_local[0];
350 yr = dx_local[1];
351 zr = dx_local[2];
352 r = sqrt(r2);
353 r3 = r * r2;
354 // Atom i descreened by atom k.
355 sum += removeSoluteDispersion(i, k);
356 // Flip the sign on {xr, yr, zr};
357 xr = -xr;
358 yr = -yr;
359 zr = -zr;
360 // Atom k descreened by atom i.
361 sum += removeSoluteDispersion(k, i);
362 }
363 }
364 // Subtract descreening.
365 edisp -= SLEVY * AWATER * sum;
366 }
367 }
368
369 @Override
370 public void start() {
371 threadID = getThreadIndex();
372 edisp = 0;
373 }
374
375 /**
376 * Remove solute dispersion between atom i and solvent due to blocking of solveny by atom k.
377 *
378 * @param i Atom i index.
379 * @param k Atom k index.
380 * @return Reduction of dispersion.
381 */
382 private double removeSoluteDispersion(int i, int k) {
383
384 // Van der Waals parameters for atom i.
385 VDWType type = atoms[i].getVDWType();
386 double epsi = type.wellDepth;
387 double rmini = type.radius / 2.0;
388
389 // Van der Waals radius for atom k.
390 double rmink = atoms[k].getVDWType().radius / 2.0;
391
392 // Parameters for atom i with water oxygen.
393 double emixo = getCombinedEps(EPSO, epsi, RMINO, rmini, epsilonRule);
394 double rmixo = getCombinedRadius(RMINO, rmini, radiusRule);
395 // Start of integration of dispersion for atom i with water oxygen.
396 double riO = rmixo / 2.0 + dispersionOffest;
397 double nO = 1.0;
398
399 // Parameters for atom i with water hydrogen.
400 double emixh = getCombinedEps(EPSH, epsi, RMINH, rmini, epsilonRule);
401 double rmixh = getCombinedRadius(RMINH, rmini, radiusRule);
402 // Start of integration of dispersion for atom i with water oxygen.
403 double riH = rmixh / 2.0 + dispersionOffest;
404 double nH = 2.0;
405
406 // Atom k blocks the interaction of atom i with solvent.
407 double sk = (rmink + soluteOffset) * dispersionOverlapFactor;
408 return interact(i, k, nO, riO, sk, rmixo, emixo) + interact(i, k, nH, riH, sk, rmixh, emixh);
409 }
410
411 /**
412 * Solvent dispersion blocking of atom i by atom k.
413 *
414 * @param i Index of atom i.
415 * @param k Index of atom k.
416 * @param factor Apply this factor to the interaction.
417 * @param ri Start of the dispersion integral.
418 * @param sk Size of the solvent blocking atom.
419 * @param rmix Combined Rmin for atom i and solvent atom.
420 * @param emix Combined Eps for atom i and solvent atom.
421 * @return Contribution of atom k to removing dispersion.
422 */
423 private double interact(
424 int i, int k, double factor, double ri, double sk, double rmix, double emix) {
425 double sum = 0.0;
426 // Nothing to do if the integral begins beyond r + sk (i.e. atom k does not exclude solvent)
427 if (ri < r + sk) {
428 // Zero out the derivative contribution of atom k.
429 double de = 0.0;
430 double sk2 = sk * sk;
431 // Compute the maximum of 1) the beginning of the integral and 2) closest edge of atom K.
432 double iStart = max(ri, r - sk);
433 // Use this as the lower limit for integrating the constant eps value below Rmin.
434 double lik = iStart;
435 // Interaction with water from lik to Rmin; nothing to do if the lower limit is greater than
436 // Rmin.
437 if (lik < rmix) {
438 double lik2 = lik * lik;
439 double lik3 = lik2 * lik;
440 double lik4 = lik3 * lik;
441 // Upper limit is the minimum of Rmin and the farthest edge of atom K.
442 double uik = min(r + sk, rmix);
443 double uik2 = uik * uik;
444 double uik3 = uik2 * uik;
445 double uik4 = uik3 * uik;
446 sum = integralBeforeRMin(emix, r, r2, sk2, lik2, lik3, lik4, uik2, uik3, uik4);
447 if (gradient) {
448 de =
449 integralBeforeRminDerivative(
450 ri, emix, rmix, r, r2, r3, sk, sk2, lik, lik2, lik3, uik, uik2, uik3);
451 }
452 }
453 // Upper limit the variable part of Uwca always the farthest edge of atom K.
454 double uik = r + sk;
455 // Interaction with water beyond Rmin, from lik to uik = r + sk.
456 if (uik > rmix) {
457 // Start the integral at the max of 1) iStart and 2) Rmin.
458 lik = max(iStart, rmix);
459 double lik2 = lik * lik;
460 double lik3 = lik2 * lik;
461 double lik4 = lik3 * lik;
462 double lik5 = lik4 * lik;
463 double lik6 = lik5 * lik;
464 double lik10 = lik5 * lik5;
465 double lik11 = lik10 * lik;
466 double lik12 = lik11 * lik;
467 double uik2 = uik * uik;
468 double uik3 = uik2 * uik;
469 double uik4 = uik3 * uik;
470 double uik5 = uik4 * uik;
471 double uik10 = uik5 * uik5;
472 double uik11 = uik10 * uik;
473 double uik12 = uik11 * uik;
474 double rmix7 = pow(rmix, 7);
475 sum +=
476 integratlAfterRmin(
477 emix, rmix7, r, r2, sk2, lik, lik2, lik3, lik4, lik5, lik10, lik11, lik12, uik,
478 uik2, uik3, uik4, uik5, uik10, uik11, uik12);
479 if (gradient) {
480 double lik13 = lik12 * lik;
481 double uik6 = uik5 * uik;
482 double uik13 = uik12 * uik;
483 de +=
484 integratlAfterRminDerivative(
485 ri, emix, rmix, rmix7, iStart, r, r2, r3, sk, sk2, lik, lik2, lik3, lik5, lik6,
486 lik12, lik13, uik, uik2, uik3, uik6, uik13);
487 }
488 }
489 // Increment the individual dispersion gradient components.
490 if (gradient) {
491 de = -de / r * factor * SLEVY * AWATER;
492 double dedx = de * xr;
493 double dedy = de * yr;
494 double dedz = de * zr;
495 grad.add(threadID, i, dedx, dedy, dedz);
496 grad.sub(threadID, k, dedx, dedy, dedz);
497 }
498 }
499 return factor * sum;
500 }
501
502 /**
503 * Integrate over the constant portion of the WCA disperion interaction Uwca(x) = eps; x < rmin.
504 *
505 * @param eps The well depth.
506 * @param rij The separation between the current atom and solvent blocking atom.
507 * @param rij2 The separation squared.
508 * @param rho2 The scaled size of the solvent blocking atom squared.
509 * @param lik2 The beginning of the integral squared.
510 * @param lik3 The beginning of the integral to the third.
511 * @param lik4 The beginning of the integral to the fourth.
512 * @param uik2 The end of the integral squared.
513 * @param uik3 The end of the integral to the third.
514 * @param uik4 The end of the integral to the fourth.
515 * @return The integral.
516 */
517 private double integralBeforeRMin(
518 double eps,
519 double rij,
520 double rij2,
521 double rho2,
522 double lik2,
523 double lik3,
524 double lik4,
525 double uik2,
526 double uik3,
527 double uik4) {
528 return -eps
529 * (4.0
530 * PI
531 * (3.0 * (lik4 - uik4) - 8.0 * rij * (lik3 - uik3) + 6.0 * (rij2 - rho2) * (lik2 - uik2))
532 / (48.0 * rij));
533 }
534
535 /**
536 * Derivative of the integral over the constant portion of the WCA disperion interaction Uwca(x)
537 * = eps; x < rmin.
538 *
539 * @param ri The beginning of the integral.
540 * @param eps The well depth.
541 * @param rmin The Rmin value.
542 * @param rij The separation between the current atom and solvent blocking atom.
543 * @param rij2 The separation squared.
544 * @param rij3 The separation to the third.
545 * @param rho The scaled size of the solvent blocking atom.
546 * @param rho2 The scaled size of the solvent blocking atom squared.
547 * @param lik The beginning of the integral.
548 * @param lik2 The beginning of the integral squared.
549 * @param lik3 The beginning of the integral to the third.
550 * @param uik The end of the integral.
551 * @param uik2 The end of the integral squared.
552 * @param uik3 The end of the integral to the third.
553 * @return The derivative of the integral.
554 */
555 private double integralBeforeRminDerivative(
556 double ri,
557 double eps,
558 double rmin,
559 double rij,
560 double rij2,
561 double rij3,
562 double rho,
563 double rho2,
564 double lik,
565 double lik2,
566 double lik3,
567 double uik,
568 double uik2,
569 double uik3) {
570 double dl;
571 if (ri > rij - rho) {
572 dl = (-lik2 + 2.0 * rij2 + 2.0 * rho2) * lik2;
573 } else {
574 dl =
575 (-lik3 + 4.0 * lik2 * rij - 6.0 * lik * rij2 + 2.0 * lik * rho2 + 4.0 * rij3
576 - 4.0 * rij * rho2)
577 * lik;
578 }
579 double du;
580 if (rij + rho > rmin) {
581 du = -(-uik2 + 2.0 * rij2 + 2.0 * rho2) * uik2;
582 } else {
583 du =
584 -(-uik3 + 4.0 * uik2 * rij - 6.0 * uik * rij2 + 2.0 * uik * rho2 + 4.0 * rij3
585 - 4.0 * rij * rho2)
586 * uik;
587 }
588 return -eps * PI * (dl + du) / (4.0 * rij2);
589 }
590
591 /**
592 * @param eps The well depth.
593 * @param rmin7 The rmin value to the seventh.
594 * @param rij The separation between the current atom and solvent blocking atom.
595 * @param rij2 The separation squared.
596 * @param rho2 The scaled size of the solvent blocking atom squared.
597 * @param lik The beginning of the integral.
598 * @param lik2 The beginning of the integral squared.
599 * @param lik3 The beginning of the integral to the third.
600 * @param lik4 The beginning of the integral to the fourth.
601 * @param lik5 The beginning of the integral to the fifth.
602 * @param lik10 The beginning of the integral to the tenth.
603 * @param lik11 The beginning of the integral to the eleventh.
604 * @param lik12 The beginning of the integral to the twelfth.
605 * @param uik The end of the integral.
606 * @param uik2 The end of the integral squared.
607 * @param uik3 The end of the integral to the third.
608 * @param uik4 The end of the integral to the fourth.
609 * @param uik5 The end of the integral to the fifth.
610 * @param uik10 The end of the integral to the tenth.
611 * @param uik11 The end of the integral to the eleventh.
612 * @param uik12 The end of the integral to the twelfth.
613 * @return The value of the integral.
614 */
615 private double integratlAfterRmin(
616 double eps,
617 double rmin7,
618 double rij,
619 double rij2,
620 double rho2,
621 double lik,
622 double lik2,
623 double lik3,
624 double lik4,
625 double lik5,
626 double lik10,
627 double lik11,
628 double lik12,
629 double uik,
630 double uik2,
631 double uik3,
632 double uik4,
633 double uik5,
634 double uik10,
635 double uik11,
636 double uik12) {
637 double er7 = eps * rmin7;
638 double term = (15.0 * uik * lik * rij * (uik4 - lik4)
639 - 10.0 * uik2 * lik2 * (uik3 - lik3)
640 + 6.0 * (rho2 - rij2) * (uik5 - lik5)) / (120.0 * rij * lik5 * uik5);
641 double term2 = (120.0 * uik * lik * rij * (uik11 - lik11)
642 - 66.0 * uik2 * lik2 * (uik10 - lik10)
643 + 55.0 * (rho2 - rij2) * (uik12 - lik12)) / (2640.0 * rij * lik12 * uik12);
644 double idisp = -2.0 * er7 * term;
645 double irep = er7 * rmin7 * term2;
646 return 4.0 * PI * (irep + idisp);
647 }
648
649 /**
650 * @param ri The beginning of the integral.
651 * @param eps The eps value.
652 * @param rmin The rmin value to the seventh.
653 * @param rmin7 The rmin value to the seventh.
654 * @param rij The separation between the current atom and solvent blocking atom.
655 * @param rij2 The separation squared.
656 * @param rij3 The separation cubed.
657 * @param rho The scaled size of the solvent blocking atom.
658 * @param rho2 The scaled size of the solvent blocking atom squared.
659 * @param lik The beginning of the integral.
660 * @param lik2 The beginning of the integral squared.
661 * @param lik3 The beginning of the integral to the third.
662 * @param lik5 The beginning of the integral to the fifth.
663 * @param lik6 The beginning of the integral to the sixth.
664 * @param lik12 The beginning of the integral to the twelfth.
665 * @param lik13 The beginning of the integral to the thirteenth.
666 * @param uik The end of the integral.
667 * @param uik2 The end of the integral squared.
668 * @param uik3 The end of the integral to the third.
669 * @param uik6 The end of the integral to the sixth.
670 * @param uik13 The end of the integral to the thirteenth.
671 * @return The value of the integral derivative.
672 */
673 private double integratlAfterRminDerivative(
674 double ri,
675 double eps,
676 double rmin,
677 double rmin7,
678 double rmax,
679 double rij,
680 double rij2,
681 double rij3,
682 double rho,
683 double rho2,
684 double lik,
685 double lik2,
686 double lik3,
687 double lik5,
688 double lik6,
689 double lik12,
690 double lik13,
691 double uik,
692 double uik2,
693 double uik3,
694 double uik6,
695 double uik13) {
696 double er7 = eps * rmin7;
697 double lowerTerm = lik2 * rij + rij3 - rij * rho2;
698 double upperTerm = uik2 * rij + rij3 - rij * rho2;
699
700 double dl;
701 if (ri > rij - rho || rmax < rmin) {
702 dl = -(-5.0 * lik2 + 3.0 * rij2 + 3.0 * rho2) / lik5;
703 } else {
704 dl = (5.0 * lik3 - 33.0 * lik * rij2 - 3.0 * lik * rho2 + 15.0 * lowerTerm) / lik6;
705 }
706 double du = -(5.0 * uik3 - 33.0 * uik * rij2 - 3.0 * uik * rho2 + 15.0 * upperTerm) / uik6;
707 double de = -2.0 * PI * er7 * (dl + du) / (15.0 * rij2);
708
709 if (ri > rij - rho || rmax < rmin) {
710 dl = -(-6.0 * lik2 + 5.0 * rij2 + 5.0 * rho2) / lik12;
711 } else {
712 dl = (6.0 * lik3 - 125.0 * lik * rij2 - 5.0 * lik * rho2 + 60.0 * lowerTerm) / lik13;
713 }
714 du = -(6.0 * uik3 - 125.0 * uik * rij2 - 5.0 * uik * rho2 + 60.0 * upperTerm) / uik13;
715 de += PI * er7 * rmin7 * (dl + du) / (60.0 * rij2);
716
717 return de;
718 }
719 }
720 }