Introduce SimulatorBuilder
[gromacs.git] / src / gromacs / tables / forcetable.cpp
blob7e10798ee3a549e4eea3d19fded1c8610d171fb2
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
37 #include "gmxpre.h"
39 #include "forcetable.h"
41 #include <cmath>
43 #include <algorithm>
45 #include "gromacs/fileio/xvgr.h"
46 #include "gromacs/math/functions.h"
47 #include "gromacs/math/units.h"
48 #include "gromacs/math/utilities.h"
49 #include "gromacs/math/vec.h"
50 #include "gromacs/mdtypes/fcdata.h"
51 #include "gromacs/mdtypes/md_enums.h"
52 #include "gromacs/mdtypes/nblist.h"
53 #include "gromacs/utility/arrayref.h"
54 #include "gromacs/utility/cstringutil.h"
55 #include "gromacs/utility/fatalerror.h"
56 #include "gromacs/utility/futil.h"
57 #include "gromacs/utility/smalloc.h"
59 /* All the possible (implemented) table functions */
60 enum {
61 etabLJ6,
62 etabLJ12,
63 etabLJ6Shift,
64 etabLJ12Shift,
65 etabShift,
66 etabRF,
67 etabRF_ZERO,
68 etabCOUL,
69 etabEwald,
70 etabEwaldSwitch,
71 etabEwaldUser,
72 etabEwaldUserSwitch,
73 etabLJ6Ewald,
74 etabLJ6Switch,
75 etabLJ12Switch,
76 etabCOULSwitch,
77 etabLJ6Encad,
78 etabLJ12Encad,
79 etabCOULEncad,
80 etabEXPMIN,
81 etabUSER,
82 etabNR
85 /** Evaluates to true if the table type contains user data. */
86 #define ETAB_USER(e) ((e) == etabUSER || \
87 (e) == etabEwaldUser || (e) == etabEwaldUserSwitch)
89 typedef struct {
90 const char *name;
91 gmx_bool bCoulomb;
92 } t_tab_props;
94 /* This structure holds name and a flag that tells whether
95 this is a Coulomb type funtion */
96 static const t_tab_props tprops[etabNR] = {
97 { "LJ6", FALSE },
98 { "LJ12", FALSE },
99 { "LJ6Shift", FALSE },
100 { "LJ12Shift", FALSE },
101 { "Shift", TRUE },
102 { "RF", TRUE },
103 { "RF-zero", TRUE },
104 { "COUL", TRUE },
105 { "Ewald", TRUE },
106 { "Ewald-Switch", TRUE },
107 { "Ewald-User", TRUE },
108 { "Ewald-User-Switch", TRUE },
109 { "LJ6Ewald", FALSE },
110 { "LJ6Switch", FALSE },
111 { "LJ12Switch", FALSE },
112 { "COULSwitch", TRUE },
113 { "LJ6-Encad shift", FALSE },
114 { "LJ12-Encad shift", FALSE },
115 { "COUL-Encad shift", TRUE },
116 { "EXPMIN", FALSE },
117 { "USER", FALSE },
120 typedef struct {
121 int nx, nx0;
122 double tabscale;
123 double *x, *v, *f;
124 } t_tabledata;
126 double v_q_ewald_lr(double beta, double r)
128 if (r == 0)
130 return beta*2/sqrt(M_PI);
132 else
134 return std::erf(beta*r)/r;
138 double v_lj_ewald_lr(double beta, double r)
140 double br, br2, br4, r6, factor;
141 if (r == 0)
143 return gmx::power6(beta)/6;
145 else
147 br = beta*r;
148 br2 = br*br;
149 br4 = br2*br2;
150 r6 = gmx::power6(r);
151 factor = (1.0 - std::exp(-br2)*(1 + br2 + 0.5*br4))/r6;
152 return factor;
156 EwaldCorrectionTables
157 generateEwaldCorrectionTables(const int numPoints,
158 const double tableScaling,
159 const real beta,
160 real_space_grid_contribution_computer v_lr)
162 real tab_max;
163 int i, i_inrange;
164 double dc, dc_new;
165 gmx_bool bOutOfRange;
166 double v_r0, v_r1, v_inrange, vi, a0, a1, a2dx;
167 double x_r0;
169 /* This function is called using either v_ewald_lr or v_lj_ewald_lr as a function argument
170 * depending on wether we should create electrostatic or Lennard-Jones Ewald tables.
173 if (numPoints < 2)
175 gmx_fatal(FARGS, "Can not make a spline table with less than 2 points");
178 const double dx = 1/tableScaling;
180 EwaldCorrectionTables tables;
181 tables.scale = tableScaling;
182 tables.tableF.resize(numPoints);
183 tables.tableV.resize(numPoints);
184 tables.tableFDV0.resize(numPoints*4);
185 gmx::ArrayRef<real> table_f = tables.tableF;
186 gmx::ArrayRef<real> table_v = tables.tableV;
187 gmx::ArrayRef<real> table_fdv0 = tables.tableFDV0;
189 /* We need some margin to be able to divide table values by r
190 * in the kernel and also to do the integration arithmetics
191 * without going out of range. Furthemore, we divide by dx below.
193 tab_max = GMX_REAL_MAX*0.0001;
195 /* This function produces a table with:
196 * maximum energy error: V'''/(6*12*sqrt(3))*dx^3
197 * maximum force error: V'''/(6*4)*dx^2
198 * The rms force error is the max error times 1/sqrt(5)=0.45.
201 bOutOfRange = FALSE;
202 i_inrange = numPoints;
203 v_inrange = 0;
204 dc = 0;
205 for (i = numPoints - 1; i >= 0; i--)
207 x_r0 = i*dx;
209 v_r0 = (*v_lr)(beta, x_r0);
211 if (!bOutOfRange)
213 i_inrange = i;
214 v_inrange = v_r0;
216 vi = v_r0;
218 else
220 /* Linear continuation for the last point in range */
221 vi = v_inrange - dc*(i - i_inrange)*dx;
224 table_v[i] = vi;
226 if (i == 0)
228 continue;
231 /* Get the potential at table point i-1 */
232 v_r1 = (*v_lr)(beta, (i-1)*dx);
234 if (v_r1 != v_r1 || v_r1 < -tab_max || v_r1 > tab_max)
236 bOutOfRange = TRUE;
239 if (!bOutOfRange)
241 /* Calculate the average second derivative times dx over interval i-1 to i.
242 * Using the function values at the end points and in the middle.
244 a2dx = (v_r0 + v_r1 - 2*(*v_lr)(beta, x_r0-0.5*dx))/(0.25*dx);
245 /* Set the derivative of the spline to match the difference in potential
246 * over the interval plus the average effect of the quadratic term.
247 * This is the essential step for minimizing the error in the force.
249 dc = (v_r0 - v_r1)/dx + 0.5*a2dx;
252 if (i == numPoints - 1)
254 /* Fill the table with the force, minus the derivative of the spline */
255 table_f[i] = -dc;
257 else
259 /* tab[i] will contain the average of the splines over the two intervals */
260 table_f[i] += -0.5*dc;
263 if (!bOutOfRange)
265 /* Make spline s(x) = a0 + a1*(x - xr) + 0.5*a2*(x - xr)^2
266 * matching the potential at the two end points
267 * and the derivative dc at the end point xr.
269 a0 = v_r0;
270 a1 = dc;
271 a2dx = (a1*dx + v_r1 - a0)*2/dx;
273 /* Set dc to the derivative at the next point */
274 dc_new = a1 - a2dx;
276 if (dc_new != dc_new || dc_new < -tab_max || dc_new > tab_max)
278 bOutOfRange = TRUE;
280 else
282 dc = dc_new;
286 table_f[(i-1)] = -0.5*dc;
288 /* Currently the last value only contains half the force: double it */
289 table_f[0] *= 2;
291 if (!table_fdv0.empty())
293 /* Copy to FDV0 table too. Allocation occurs in forcerec.c,
294 * init_ewald_f_table().
296 for (i = 0; i < numPoints - 1; i++)
298 table_fdv0[4*i] = table_f[i];
299 table_fdv0[4*i+1] = table_f[i+1]-table_f[i];
300 table_fdv0[4*i+2] = table_v[i];
301 table_fdv0[4*i+3] = 0.0;
303 const int lastPoint = numPoints - 1;
304 table_fdv0[4*lastPoint] = table_f[lastPoint];
305 table_fdv0[4*lastPoint+1] = -table_f[lastPoint];
306 table_fdv0[4*lastPoint+2] = table_v[lastPoint];
307 table_fdv0[4*lastPoint+3] = 0.0;
310 return tables;
313 /* Returns the spacing for a function using the maximum of
314 * the third derivative, x_scale (unit 1/length)
315 * and function tolerance.
317 static double spline3_table_scale(double third_deriv_max,
318 double x_scale,
319 double func_tol)
321 double deriv_tol;
322 double sc_deriv, sc_func;
324 /* Force tolerance: single precision accuracy */
325 deriv_tol = GMX_FLOAT_EPS;
326 sc_deriv = sqrt(third_deriv_max/(6*4*deriv_tol*x_scale))*x_scale;
328 /* Don't try to be more accurate on energy than the precision */
329 func_tol = std::max(func_tol, static_cast<double>(GMX_REAL_EPS));
330 sc_func = std::cbrt(third_deriv_max/(6*12*std::sqrt(3.0)*func_tol))*x_scale;
332 return std::max(sc_deriv, sc_func);
335 /* The scale (1/spacing) for third order spline interpolation
336 * of the Ewald mesh contribution which needs to be subtracted
337 * from the non-bonded interactions.
338 * Since there is currently only one spacing for Coulomb and LJ,
339 * the finest spacing is used if both Ewald types are present.
341 * Note that we could also implement completely separate tables
342 * for Coulomb and LJ Ewald, each with their own spacing.
343 * The current setup with the same spacing can provide slightly
344 * faster kernels with both Coulomb and LJ Ewald, especially
345 * when interleaving both tables (currently not implemented).
347 real ewald_spline3_table_scale(const interaction_const_t &ic,
348 const bool generateCoulombTables,
349 const bool generateVdwTables)
351 GMX_RELEASE_ASSERT(!generateCoulombTables || EEL_PME_EWALD(ic.eeltype), "Can only use tables with Ewald");
352 GMX_RELEASE_ASSERT(!generateVdwTables || EVDW_PME(ic.vdwtype), "Can only use tables with Ewald");
354 real sc = 0;
356 if (generateCoulombTables)
358 GMX_RELEASE_ASSERT(ic.ewaldcoeff_q > 0, "The Ewald coefficient shoule be positive");
360 double erf_x_d3 = 1.0522; /* max of (erf(x)/x)''' */
361 double etol;
362 real sc_q;
364 /* Energy tolerance: 0.1 times the cut-off jump */
365 etol = 0.1*std::erfc(ic.ewaldcoeff_q*ic.rcoulomb);
367 sc_q = spline3_table_scale(erf_x_d3, ic.ewaldcoeff_q, etol);
369 if (debug)
371 fprintf(debug, "Ewald Coulomb quadratic spline table spacing: %f nm\n", 1/sc_q);
374 sc = std::max(sc, sc_q);
377 if (generateVdwTables)
379 GMX_RELEASE_ASSERT(ic.ewaldcoeff_lj > 0, "The Ewald coefficient shoule be positive");
381 double func_d3 = 0.42888; /* max of (x^-6 (1 - exp(-x^2)(1+x^2+x^4/2)))''' */
382 double xrc2, etol;
383 real sc_lj;
385 /* Energy tolerance: 0.1 times the cut-off jump */
386 xrc2 = gmx::square(ic.ewaldcoeff_lj*ic.rvdw);
387 etol = 0.1*std::exp(-xrc2)*(1 + xrc2 + xrc2*xrc2/2.0);
389 sc_lj = spline3_table_scale(func_d3, ic.ewaldcoeff_lj, etol);
391 if (debug)
393 fprintf(debug, "Ewald LJ quadratic spline table spacing: %f nm\n", 1/sc_lj);
396 sc = std::max(sc, sc_lj);
399 return sc;
402 static void copy2table(int n, int offset, int stride,
403 const double x[], const double Vtab[], const double Ftab[], real scalefactor,
404 real dest[])
406 /* Use double prec. for the intermediary variables
407 * and temporary x/vtab/vtab2 data to avoid unnecessary
408 * loss of precision.
410 int i, nn0;
411 double F, G, H, h;
413 h = 0;
414 for (i = 0; (i < n); i++)
416 if (i < n-1)
418 h = x[i+1] - x[i];
419 F = -Ftab[i]*h;
420 G = 3*(Vtab[i+1] - Vtab[i]) + (Ftab[i+1] + 2*Ftab[i])*h;
421 H = -2*(Vtab[i+1] - Vtab[i]) - (Ftab[i+1] + Ftab[i])*h;
423 else
425 /* Fill the last entry with a linear potential,
426 * this is mainly for rounding issues with angle and dihedral potentials.
428 F = -Ftab[i]*h;
429 G = 0;
430 H = 0;
432 nn0 = offset + i*stride;
433 dest[nn0] = scalefactor*Vtab[i];
434 dest[nn0+1] = scalefactor*F;
435 dest[nn0+2] = scalefactor*G;
436 dest[nn0+3] = scalefactor*H;
440 static void init_table(int n, int nx0,
441 double tabscale, t_tabledata *td, gmx_bool bAlloc)
443 td->nx = n;
444 td->nx0 = nx0;
445 td->tabscale = tabscale;
446 if (bAlloc)
448 snew(td->x, td->nx);
449 snew(td->v, td->nx);
450 snew(td->f, td->nx);
454 static void spline_forces(int nx, double h, const double v[], gmx_bool bS3, gmx_bool bE3,
455 double f[])
457 int start, end, i;
458 double v3, b_s, b_e, b;
459 double beta, *gamma;
461 /* Formulas can be found in:
462 * H.J.C. Berendsen, Simulating the Physical World, Cambridge 2007
465 if (nx < 4 && (bS3 || bE3))
467 gmx_fatal(FARGS, "Can not generate splines with third derivative boundary conditions with less than 4 (%d) points", nx);
470 /* To make life easy we initially set the spacing to 1
471 * and correct for this at the end.
473 if (bS3)
475 /* Fit V''' at the start */
476 v3 = v[3] - 3*v[2] + 3*v[1] - v[0];
477 if (debug)
479 fprintf(debug, "The left third derivative is %g\n", v3/(h*h*h));
481 b_s = 2*(v[1] - v[0]) + v3/6;
482 start = 0;
484 if (FALSE)
486 /* Fit V'' at the start */
487 real v2;
489 v2 = -v[3] + 4*v[2] - 5*v[1] + 2*v[0];
490 /* v2 = v[2] - 2*v[1] + v[0]; */
491 if (debug)
493 fprintf(debug, "The left second derivative is %g\n", v2/(h*h));
495 b_s = 3*(v[1] - v[0]) - v2/2;
496 start = 0;
499 else
501 b_s = 3*(v[2] - v[0]) + f[0]*h;
502 start = 1;
504 if (bE3)
506 /* Fit V''' at the end */
507 v3 = v[nx-1] - 3*v[nx-2] + 3*v[nx-3] - v[nx-4];
508 if (debug)
510 fprintf(debug, "The right third derivative is %g\n", v3/(h*h*h));
512 b_e = 2*(v[nx-1] - v[nx-2]) + v3/6;
513 end = nx;
515 else
517 /* V'=0 at the end */
518 b_e = 3*(v[nx-1] - v[nx-3]) + f[nx-1]*h;
519 end = nx - 1;
522 snew(gamma, nx);
523 beta = (bS3 ? 1 : 4);
525 /* For V'' fitting */
526 /* beta = (bS3 ? 2 : 4); */
528 f[start] = b_s/beta;
529 for (i = start+1; i < end; i++)
531 gamma[i] = 1/beta;
532 beta = 4 - gamma[i];
533 b = 3*(v[i+1] - v[i-1]);
534 f[i] = (b - f[i-1])/beta;
536 gamma[end-1] = 1/beta;
537 beta = (bE3 ? 1 : 4) - gamma[end-1];
538 f[end-1] = (b_e - f[end-2])/beta;
540 for (i = end-2; i >= start; i--)
542 f[i] -= gamma[i+1]*f[i+1];
544 sfree(gamma);
546 /* Correct for the minus sign and the spacing */
547 for (i = start; i < end; i++)
549 f[i] = -f[i]/h;
553 static void set_forces(FILE *fp, int angle,
554 int nx, double h, double v[], double f[],
555 int table)
557 int start, end;
559 if (angle == 2)
561 gmx_fatal(FARGS,
562 "Force generation for dihedral tables is not (yet) implemented");
565 start = 0;
566 while (v[start] == 0)
568 start++;
571 end = nx;
572 while (v[end-1] == 0)
574 end--;
576 if (end > nx - 2)
578 end = nx;
580 else
582 end++;
585 if (fp)
587 fprintf(fp, "Generating forces for table %d, boundary conditions: V''' at %g, %s at %g\n",
588 table+1, start*h, end == nx ? "V'''" : "V'=0", (end-1)*h);
590 spline_forces(end-start, h, v+start, TRUE, end == nx, f+start);
593 static void read_tables(FILE *fp, const char *filename,
594 int ntab, int angle, t_tabledata td[])
596 char buf[STRLEN];
597 double **yy = nullptr, start, end, dx0, dx1, ssd, vm, vp, f, numf;
598 int k, i, nx, nx0 = 0, ny, nny, ns;
599 gmx_bool bAllZero, bZeroV, bZeroF;
600 double tabscale;
602 nny = 2*ntab+1;
603 std::string libfn = gmx::findLibraryFile(filename);
604 nx = read_xvg(libfn.c_str(), &yy, &ny);
605 if (ny != nny)
607 gmx_fatal(FARGS, "Trying to read file %s, but nr columns = %d, should be %d",
608 libfn.c_str(), ny, nny);
610 if (angle == 0)
612 if (yy[0][0] != 0.0)
614 gmx_fatal(FARGS,
615 "The first distance in file %s is %f nm instead of %f nm",
616 libfn.c_str(), yy[0][0], 0.0);
619 else
621 if (angle == 1)
623 start = 0.0;
625 else
627 start = -180.0;
629 end = 180.0;
630 if (yy[0][0] != start || yy[0][nx-1] != end)
632 gmx_fatal(FARGS, "The angles in file %s should go from %f to %f instead of %f to %f\n",
633 libfn.c_str(), start, end, yy[0][0], yy[0][nx-1]);
637 tabscale = (nx-1)/(yy[0][nx-1] - yy[0][0]);
639 if (fp)
641 fprintf(fp, "Read user tables from %s with %d data points.\n", libfn.c_str(), nx);
642 if (angle == 0)
644 fprintf(fp, "Tabscale = %g points/nm\n", tabscale);
648 bAllZero = TRUE;
649 for (k = 0; k < ntab; k++)
651 bZeroV = TRUE;
652 bZeroF = TRUE;
653 for (i = 0; (i < nx); i++)
655 if (i >= 2)
657 dx0 = yy[0][i-1] - yy[0][i-2];
658 dx1 = yy[0][i] - yy[0][i-1];
659 /* Check for 1% deviation in spacing */
660 if (fabs(dx1 - dx0) >= 0.005*(fabs(dx0) + fabs(dx1)))
662 gmx_fatal(FARGS, "In table file '%s' the x values are not equally spaced: %f %f %f", filename, yy[0][i-2], yy[0][i-1], yy[0][i]);
665 if (yy[1+k*2][i] != 0)
667 bZeroV = FALSE;
668 if (bAllZero)
670 bAllZero = FALSE;
671 nx0 = i;
673 if (yy[1+k*2][i] > 0.01*GMX_REAL_MAX ||
674 yy[1+k*2][i] < -0.01*GMX_REAL_MAX)
676 gmx_fatal(FARGS, "Out of range potential value %g in file '%s'",
677 yy[1+k*2][i], filename);
680 if (yy[1+k*2+1][i] != 0)
682 bZeroF = FALSE;
683 if (bAllZero)
685 bAllZero = FALSE;
686 nx0 = i;
688 if (yy[1+k*2+1][i] > 0.01*GMX_REAL_MAX ||
689 yy[1+k*2+1][i] < -0.01*GMX_REAL_MAX)
691 gmx_fatal(FARGS, "Out of range force value %g in file '%s'",
692 yy[1+k*2+1][i], filename);
697 if (!bZeroV && bZeroF)
699 set_forces(fp, angle, nx, 1/tabscale, yy[1+k*2], yy[1+k*2+1], k);
701 else
703 /* Check if the second column is close to minus the numerical
704 * derivative of the first column.
706 ssd = 0;
707 ns = 0;
708 for (i = 1; (i < nx-1); i++)
710 vm = yy[1+2*k][i-1];
711 vp = yy[1+2*k][i+1];
712 f = yy[1+2*k+1][i];
713 if (vm != 0 && vp != 0 && f != 0)
715 /* Take the centered difference */
716 numf = -(vp - vm)*0.5*tabscale;
717 if (f + numf != 0)
719 ssd += fabs(2*(f - numf)/(f + numf));
721 ns++;
724 if (ns > 0)
726 ssd /= ns;
727 sprintf(buf, "For the %d non-zero entries for table %d in %s the forces deviate on average %" PRId64
728 "%% from minus the numerical derivative of the potential\n",
729 ns, k, libfn.c_str(), gmx::roundToInt64(100*ssd));
730 if (debug)
732 fprintf(debug, "%s", buf);
734 if (ssd > 0.2)
736 if (fp)
738 fprintf(fp, "\nWARNING: %s\n", buf);
740 fprintf(stderr, "\nWARNING: %s\n", buf);
745 if (bAllZero && fp)
747 fprintf(fp, "\nNOTE: All elements in table %s are zero\n\n", libfn.c_str());
750 for (k = 0; (k < ntab); k++)
752 init_table(nx, nx0, tabscale, &(td[k]), TRUE);
753 for (i = 0; (i < nx); i++)
755 td[k].x[i] = yy[0][i];
756 td[k].v[i] = yy[2*k+1][i];
757 td[k].f[i] = yy[2*k+2][i];
760 for (i = 0; (i < ny); i++)
762 sfree(yy[i]);
764 sfree(yy);
767 static void done_tabledata(t_tabledata *td)
769 if (!td)
771 return;
774 sfree(td->x);
775 sfree(td->v);
776 sfree(td->f);
779 static void fill_table(t_tabledata *td, int tp, const interaction_const_t *ic,
780 gmx_bool b14only)
782 /* Fill the table according to the formulas in the manual.
783 * In principle, we only need the potential and the second
784 * derivative, but then we would have to do lots of calculations
785 * in the inner loop. By precalculating some terms (see manual)
786 * we get better eventual performance, despite a larger table.
788 * Since some of these higher-order terms are very small,
789 * we always use double precision to calculate them here, in order
790 * to avoid unnecessary loss of precision.
792 int i;
793 double reppow, p;
794 double r1, rc, r12, r13;
795 double r, r2, r6, rc2, rc6, rc12;
796 double expr, Vtab, Ftab;
797 /* Parameters for David's function */
798 double A = 0, B = 0, C = 0, A_3 = 0, B_4 = 0;
799 /* Parameters for the switching function */
800 double ksw, swi, swi1;
801 /* Temporary parameters */
802 gmx_bool bPotentialSwitch, bForceSwitch, bPotentialShift;
803 double ewc = ic->ewaldcoeff_q;
804 double ewclj = ic->ewaldcoeff_lj;
805 double Vcut = 0;
807 if (b14only)
809 bPotentialSwitch = FALSE;
810 bForceSwitch = FALSE;
811 bPotentialShift = FALSE;
813 else
815 bPotentialSwitch = ((tp == etabLJ6Switch) || (tp == etabLJ12Switch) ||
816 (tp == etabCOULSwitch) ||
817 (tp == etabEwaldSwitch) || (tp == etabEwaldUserSwitch) ||
818 (tprops[tp].bCoulomb && (ic->coulomb_modifier == eintmodPOTSWITCH)) ||
819 (!tprops[tp].bCoulomb && (ic->vdw_modifier == eintmodPOTSWITCH)));
820 bForceSwitch = ((tp == etabLJ6Shift) || (tp == etabLJ12Shift) ||
821 (tp == etabShift) ||
822 (tprops[tp].bCoulomb && (ic->coulomb_modifier == eintmodFORCESWITCH)) ||
823 (!tprops[tp].bCoulomb && (ic->vdw_modifier == eintmodFORCESWITCH)));
824 bPotentialShift = ((tprops[tp].bCoulomb && (ic->coulomb_modifier == eintmodPOTSHIFT)) ||
825 (!tprops[tp].bCoulomb && (ic->vdw_modifier == eintmodPOTSHIFT)));
828 reppow = ic->reppow;
830 if (tprops[tp].bCoulomb)
832 r1 = ic->rcoulomb_switch;
833 rc = ic->rcoulomb;
835 else
837 r1 = ic->rvdw_switch;
838 rc = ic->rvdw;
840 if (bPotentialSwitch)
842 ksw = 1.0/(gmx::power5(rc-r1));
844 else
846 ksw = 0.0;
848 if (bForceSwitch)
850 if (tp == etabShift)
852 p = 1;
854 else if (tp == etabLJ6Shift)
856 p = 6;
858 else
860 p = reppow;
863 A = p * ((p+1)*r1-(p+4)*rc)/(std::pow(rc, p+2)*gmx::square(rc-r1));
864 B = -p * ((p+1)*r1-(p+3)*rc)/(std::pow(rc, p+2)*gmx::power3(rc-r1));
865 C = 1.0/std::pow(rc, p)-A/3.0*gmx::power3(rc-r1)-B/4.0*gmx::power4(rc-r1);
866 if (tp == etabLJ6Shift)
868 A = -A;
869 B = -B;
870 C = -C;
872 A_3 = A/3.0;
873 B_4 = B/4.0;
875 if (debug)
877 fprintf(debug, "Setting up tables\n"); fflush(debug);
880 if (bPotentialShift)
882 rc2 = rc*rc;
883 rc6 = 1.0/(rc2*rc2*rc2);
884 if (gmx_within_tol(reppow, 12.0, 10*GMX_DOUBLE_EPS))
886 rc12 = rc6*rc6;
888 else
890 rc12 = std::pow(rc, -reppow);
893 switch (tp)
895 case etabLJ6:
896 /* Dispersion */
897 Vcut = -rc6;
898 break;
899 case etabLJ6Ewald:
900 Vcut = -rc6*exp(-ewclj*ewclj*rc2)*(1 + ewclj*ewclj*rc2 + gmx::power4(ewclj)*rc2*rc2/2);
901 break;
902 case etabLJ12:
903 /* Repulsion */
904 Vcut = rc12;
905 break;
906 case etabCOUL:
907 Vcut = 1.0/rc;
908 break;
909 case etabEwald:
910 case etabEwaldSwitch:
911 Vcut = std::erfc(ewc*rc)/rc;
912 break;
913 case etabEwaldUser:
914 /* Only calculate minus the reciprocal space contribution */
915 Vcut = -std::erf(ewc*rc)/rc;
916 break;
917 case etabRF:
918 case etabRF_ZERO:
919 /* No need for preventing the usage of modifiers with RF */
920 Vcut = 0.0;
921 break;
922 case etabEXPMIN:
923 Vcut = exp(-rc);
924 break;
925 default:
926 gmx_fatal(FARGS, "Cannot apply new potential-shift modifier to interaction type '%s' yet. (%s,%d)",
927 tprops[tp].name, __FILE__, __LINE__);
931 for (i = 0; (i < td->nx); i++)
933 td->x[i] = i/td->tabscale;
935 for (i = td->nx0; (i < td->nx); i++)
937 r = td->x[i];
938 r2 = r*r;
939 r6 = 1.0/(r2*r2*r2);
940 if (gmx_within_tol(reppow, 12.0, 10*GMX_DOUBLE_EPS))
942 r12 = r6*r6;
944 else
946 r12 = std::pow(r, -reppow);
948 Vtab = 0.0;
949 Ftab = 0.0;
950 if (bPotentialSwitch)
952 /* swi is function, swi1 1st derivative and swi2 2nd derivative */
953 /* The switch function is 1 for r<r1, 0 for r>rc, and smooth for
954 * r1<=r<=rc. The 1st and 2nd derivatives are both zero at
955 * r1 and rc.
956 * ksw is just the constant 1/(rc-r1)^5, to save some calculations...
958 if (r <= r1)
960 swi = 1.0;
961 swi1 = 0.0;
963 else if (r >= rc)
965 swi = 0.0;
966 swi1 = 0.0;
968 else
970 swi = 1 - 10*gmx::power3(r-r1)*ksw*gmx::square(rc-r1)
971 + 15*gmx::power4(r-r1)*ksw*(rc-r1) - 6*gmx::power5(r-r1)*ksw;
972 swi1 = -30*gmx::square(r-r1)*ksw*gmx::square(rc-r1)
973 + 60*gmx::power3(r-r1)*ksw*(rc-r1) - 30*gmx::power4(r-r1)*ksw;
976 else /* not really needed, but avoids compiler warnings... */
978 swi = 1.0;
979 swi1 = 0.0;
982 rc6 = rc*rc*rc;
983 rc6 = 1.0/(rc6*rc6);
985 switch (tp)
987 case etabLJ6:
988 /* Dispersion */
989 Vtab = -r6;
990 Ftab = 6.0*Vtab/r;
991 break;
992 case etabLJ6Switch:
993 case etabLJ6Shift:
994 /* Dispersion */
995 if (r < rc)
997 Vtab = -r6;
998 Ftab = 6.0*Vtab/r;
999 break;
1001 break;
1002 case etabLJ12:
1003 /* Repulsion */
1004 Vtab = r12;
1005 Ftab = reppow*Vtab/r;
1006 break;
1007 case etabLJ12Switch:
1008 case etabLJ12Shift:
1009 /* Repulsion */
1010 if (r < rc)
1012 Vtab = r12;
1013 Ftab = reppow*Vtab/r;
1015 break;
1016 case etabLJ6Encad:
1017 if (r < rc)
1019 Vtab = -(r6-6.0*(rc-r)*rc6/rc-rc6);
1020 Ftab = -(6.0*r6/r-6.0*rc6/rc);
1022 else /* r>rc */
1024 Vtab = 0;
1025 Ftab = 0;
1027 break;
1028 case etabLJ12Encad:
1029 if (r < rc)
1031 Vtab = -(r6-6.0*(rc-r)*rc6/rc-rc6);
1032 Ftab = -(6.0*r6/r-6.0*rc6/rc);
1034 else /* r>rc */
1036 Vtab = 0;
1037 Ftab = 0;
1039 break;
1040 case etabCOUL:
1041 Vtab = 1.0/r;
1042 Ftab = 1.0/r2;
1043 break;
1044 case etabCOULSwitch:
1045 case etabShift:
1046 if (r < rc)
1048 Vtab = 1.0/r;
1049 Ftab = 1.0/r2;
1051 break;
1052 case etabEwald:
1053 case etabEwaldSwitch:
1054 Vtab = std::erfc(ewc*r)/r;
1055 Ftab = std::erfc(ewc*r)/r2+exp(-(ewc*ewc*r2))*ewc*M_2_SQRTPI/r;
1056 break;
1057 case etabEwaldUser:
1058 case etabEwaldUserSwitch:
1059 /* Only calculate the negative of the reciprocal space contribution */
1060 Vtab = -std::erf(ewc*r)/r;
1061 Ftab = -std::erf(ewc*r)/r2+exp(-(ewc*ewc*r2))*ewc*M_2_SQRTPI/r;
1062 break;
1063 case etabLJ6Ewald:
1064 Vtab = -r6*exp(-ewclj*ewclj*r2)*(1 + ewclj*ewclj*r2 + gmx::power4(ewclj)*r2*r2/2);
1065 Ftab = 6.0*Vtab/r - r6*exp(-ewclj*ewclj*r2)*gmx::power5(ewclj)*ewclj*r2*r2*r;
1066 break;
1067 case etabRF:
1068 case etabRF_ZERO:
1069 Vtab = 1.0/r + ic->k_rf*r2 - ic->c_rf;
1070 Ftab = 1.0/r2 - 2*ic->k_rf*r;
1071 if (tp == etabRF_ZERO && r >= rc)
1073 Vtab = 0;
1074 Ftab = 0;
1076 break;
1077 case etabEXPMIN:
1078 expr = exp(-r);
1079 Vtab = expr;
1080 Ftab = expr;
1081 break;
1082 case etabCOULEncad:
1083 if (r < rc)
1085 Vtab = 1.0/r-(rc-r)/(rc*rc)-1.0/rc;
1086 Ftab = 1.0/r2-1.0/(rc*rc);
1088 else /* r>rc */
1090 Vtab = 0;
1091 Ftab = 0;
1093 break;
1094 default:
1095 gmx_fatal(FARGS, "Table type %d not implemented yet. (%s,%d)",
1096 tp, __FILE__, __LINE__);
1098 if (bForceSwitch)
1100 /* Normal coulomb with cut-off correction for potential */
1101 if (r < rc)
1103 Vtab -= C;
1104 /* If in Shifting range add something to it */
1105 if (r > r1)
1107 r12 = (r-r1)*(r-r1);
1108 r13 = (r-r1)*r12;
1109 Vtab += -A_3*r13 - B_4*r12*r12;
1110 Ftab += A*r12 + B*r13;
1113 else
1115 /* Make sure interactions are zero outside cutoff with modifiers */
1116 Vtab = 0;
1117 Ftab = 0;
1120 if (bPotentialShift)
1122 if (r < rc)
1124 Vtab -= Vcut;
1126 else
1128 /* Make sure interactions are zero outside cutoff with modifiers */
1129 Vtab = 0;
1130 Ftab = 0;
1134 if (ETAB_USER(tp))
1136 Vtab += td->v[i];
1137 Ftab += td->f[i];
1140 if (bPotentialSwitch)
1142 if (r >= rc)
1144 /* Make sure interactions are zero outside cutoff with modifiers */
1145 Vtab = 0;
1146 Ftab = 0;
1148 else if (r > r1)
1150 Ftab = Ftab*swi - Vtab*swi1;
1151 Vtab = Vtab*swi;
1154 /* Convert to single precision when we store to mem */
1155 td->v[i] = Vtab;
1156 td->f[i] = Ftab;
1159 /* Continue the table linearly from nx0 to 0.
1160 * These values are only required for energy minimization with overlap or TPI.
1162 for (i = td->nx0-1; i >= 0; i--)
1164 td->v[i] = td->v[i+1] + td->f[i+1]*(td->x[i+1] - td->x[i]);
1165 td->f[i] = td->f[i+1];
1169 static void set_table_type(int tabsel[], const interaction_const_t *ic, gmx_bool b14only)
1171 int eltype, vdwtype;
1173 /* Set the different table indices.
1174 * Coulomb first.
1178 if (b14only)
1180 switch (ic->eeltype)
1182 case eelUSER:
1183 case eelPMEUSER:
1184 case eelPMEUSERSWITCH:
1185 eltype = eelUSER;
1186 break;
1187 default:
1188 eltype = eelCUT;
1191 else
1193 eltype = ic->eeltype;
1196 switch (eltype)
1198 case eelCUT:
1199 tabsel[etiCOUL] = etabCOUL;
1200 break;
1201 case eelPOISSON:
1202 tabsel[etiCOUL] = etabShift;
1203 break;
1204 case eelSHIFT:
1205 if (ic->rcoulomb > ic->rcoulomb_switch)
1207 tabsel[etiCOUL] = etabShift;
1209 else
1211 tabsel[etiCOUL] = etabCOUL;
1213 break;
1214 case eelEWALD:
1215 case eelPME:
1216 case eelP3M_AD:
1217 tabsel[etiCOUL] = etabEwald;
1218 break;
1219 case eelPMESWITCH:
1220 tabsel[etiCOUL] = etabEwaldSwitch;
1221 break;
1222 case eelPMEUSER:
1223 tabsel[etiCOUL] = etabEwaldUser;
1224 break;
1225 case eelPMEUSERSWITCH:
1226 tabsel[etiCOUL] = etabEwaldUserSwitch;
1227 break;
1228 case eelRF:
1229 case eelRF_ZERO:
1230 tabsel[etiCOUL] = etabRF_ZERO;
1231 break;
1232 case eelSWITCH:
1233 tabsel[etiCOUL] = etabCOULSwitch;
1234 break;
1235 case eelUSER:
1236 tabsel[etiCOUL] = etabUSER;
1237 break;
1238 case eelENCADSHIFT:
1239 tabsel[etiCOUL] = etabCOULEncad;
1240 break;
1241 default:
1242 gmx_fatal(FARGS, "Invalid eeltype %d", eltype);
1245 /* Van der Waals time */
1246 if (ic->useBuckingham && !b14only)
1248 tabsel[etiLJ6] = etabLJ6;
1249 tabsel[etiLJ12] = etabEXPMIN;
1251 else
1253 if (b14only && ic->vdwtype != evdwUSER)
1255 vdwtype = evdwCUT;
1257 else
1259 vdwtype = ic->vdwtype;
1262 switch (vdwtype)
1264 case evdwSWITCH:
1265 tabsel[etiLJ6] = etabLJ6Switch;
1266 tabsel[etiLJ12] = etabLJ12Switch;
1267 break;
1268 case evdwSHIFT:
1269 tabsel[etiLJ6] = etabLJ6Shift;
1270 tabsel[etiLJ12] = etabLJ12Shift;
1271 break;
1272 case evdwUSER:
1273 tabsel[etiLJ6] = etabUSER;
1274 tabsel[etiLJ12] = etabUSER;
1275 break;
1276 case evdwCUT:
1277 tabsel[etiLJ6] = etabLJ6;
1278 tabsel[etiLJ12] = etabLJ12;
1279 break;
1280 case evdwENCADSHIFT:
1281 tabsel[etiLJ6] = etabLJ6Encad;
1282 tabsel[etiLJ12] = etabLJ12Encad;
1283 break;
1284 case evdwPME:
1285 tabsel[etiLJ6] = etabLJ6Ewald;
1286 tabsel[etiLJ12] = etabLJ12;
1287 break;
1288 default:
1289 gmx_fatal(FARGS, "Invalid vdwtype %d in %s line %d", vdwtype,
1290 __FILE__, __LINE__);
1293 if (!b14only && ic->vdw_modifier != eintmodNONE)
1295 if (ic->vdw_modifier != eintmodPOTSHIFT &&
1296 ic->vdwtype != evdwCUT)
1298 gmx_incons("Potential modifiers other than potential-shift are only implemented for LJ cut-off");
1301 /* LJ-PME and other (shift-only) modifiers are handled by applying the modifiers
1302 * to the original interaction forms when we fill the table, so we only check cutoffs here.
1304 if (ic->vdwtype == evdwCUT)
1306 switch (ic->vdw_modifier)
1308 case eintmodNONE:
1309 case eintmodPOTSHIFT:
1310 case eintmodEXACTCUTOFF:
1311 /* No modification */
1312 break;
1313 case eintmodPOTSWITCH:
1314 tabsel[etiLJ6] = etabLJ6Switch;
1315 tabsel[etiLJ12] = etabLJ12Switch;
1316 break;
1317 case eintmodFORCESWITCH:
1318 tabsel[etiLJ6] = etabLJ6Shift;
1319 tabsel[etiLJ12] = etabLJ12Shift;
1320 break;
1321 default:
1322 gmx_incons("Unsupported vdw_modifier");
1329 t_forcetable *make_tables(FILE *out,
1330 const interaction_const_t *ic,
1331 const char *fn,
1332 real rtab, int flags)
1334 t_tabledata *td;
1335 gmx_bool b14only, useUserTable;
1336 int nx0, tabsel[etiNR];
1337 real scalefactor;
1339 t_forcetable *table = new t_forcetable(GMX_TABLE_INTERACTION_ELEC_VDWREP_VDWDISP,
1340 GMX_TABLE_FORMAT_CUBICSPLINE_YFGH);
1342 b14only = ((flags & GMX_MAKETABLES_14ONLY) != 0);
1344 if (flags & GMX_MAKETABLES_FORCEUSER)
1346 tabsel[etiCOUL] = etabUSER;
1347 tabsel[etiLJ6] = etabUSER;
1348 tabsel[etiLJ12] = etabUSER;
1350 else
1352 set_table_type(tabsel, ic, b14only);
1354 snew(td, etiNR);
1355 table->r = rtab;
1356 table->scale = 0;
1357 table->n = 0;
1359 table->formatsize = 4;
1360 table->ninteractions = etiNR;
1361 table->stride = table->formatsize*table->ninteractions;
1363 /* Check whether we have to read or generate */
1364 useUserTable = FALSE;
1365 for (unsigned int i = 0; (i < etiNR); i++)
1367 if (ETAB_USER(tabsel[i]))
1369 useUserTable = TRUE;
1372 if (useUserTable)
1374 read_tables(out, fn, etiNR, 0, td);
1375 if (rtab == 0 || (flags & GMX_MAKETABLES_14ONLY))
1377 table->n = td[0].nx;
1379 else
1381 if (td[0].x[td[0].nx-1] < rtab)
1383 gmx_fatal(FARGS, "Tables in file %s not long enough for cut-off:\n"
1384 "\tshould be at least %f nm\n", fn, rtab);
1386 table->n = gmx::roundToInt(rtab*td[0].tabscale);
1388 table->scale = td[0].tabscale;
1389 nx0 = td[0].nx0;
1391 else
1393 // No tables are read
1394 #if GMX_DOUBLE
1395 table->scale = 2000.0;
1396 #else
1397 table->scale = 500.0;
1398 #endif
1399 table->n = static_cast<int>(rtab*table->scale);
1400 nx0 = 10;
1403 /* Each table type (e.g. coul,lj6,lj12) requires four
1404 * numbers per table->n+1 data points. For performance reasons we want
1405 * the table data to be aligned to a 32-byte boundary.
1407 snew_aligned(table->data, table->stride*(table->n+1)*sizeof(real), 32);
1409 for (int k = 0; (k < etiNR); k++)
1411 /* Now fill data for tables that have not been read
1412 * or add the Ewald long-range correction for Ewald user tables.
1414 if (tabsel[k] != etabUSER)
1416 real scale = table->scale;
1417 if (ic->useBuckingham &&
1418 (ic->buckinghamBMax != 0) &&
1419 tabsel[k] == etabEXPMIN)
1421 scale /= ic->buckinghamBMax;
1423 init_table(table->n, nx0, scale, &(td[k]), !useUserTable);
1425 fill_table(&(td[k]), tabsel[k], ic, b14only);
1426 if (out)
1428 fprintf(out, "Generated table with %d data points for %s%s.\n"
1429 "Tabscale = %g points/nm\n",
1430 td[k].nx, b14only ? "1-4 " : "", tprops[tabsel[k]].name,
1431 td[k].tabscale);
1435 /* Set scalefactor for c6/c12 tables. This is because we save flops in the non-table kernels
1436 * by including the derivative constants (6.0 or 12.0) in the parameters, since
1437 * we no longer calculate force in most steps. This means the c6/c12 parameters
1438 * have been scaled up, so we need to scale down the table interactions too.
1439 * It comes here since we need to scale user tables too.
1441 if (k == etiLJ6)
1443 scalefactor = 1.0/6.0;
1445 else if (k == etiLJ12 && tabsel[k] != etabEXPMIN)
1447 scalefactor = 1.0/12.0;
1449 else
1451 scalefactor = 1.0;
1454 copy2table(table->n, k*table->formatsize, table->stride, td[k].x, td[k].v, td[k].f, scalefactor, table->data);
1456 done_tabledata(&(td[k]));
1458 sfree(td);
1460 return table;
1463 bondedtable_t make_bonded_table(FILE *fplog, const char *fn, int angle)
1465 t_tabledata td;
1466 int i;
1467 bondedtable_t tab;
1468 int stride = 4;
1470 read_tables(fplog, fn, 1, angle, &td);
1471 if (angle > 0)
1473 /* Convert the table from degrees to radians */
1474 for (i = 0; i < td.nx; i++)
1476 td.x[i] *= DEG2RAD;
1477 td.f[i] *= RAD2DEG;
1479 td.tabscale *= RAD2DEG;
1481 tab.n = td.nx;
1482 tab.scale = td.tabscale;
1483 snew(tab.data, tab.n*stride);
1484 copy2table(tab.n, 0, stride, td.x, td.v, td.f, 1.0, tab.data);
1485 done_tabledata(&td);
1487 return tab;
1490 std::unique_ptr<t_forcetable>
1491 makeDispersionCorrectionTable(FILE *fp,
1492 const interaction_const_t *ic,
1493 real rtab,
1494 const char *tabfn)
1496 GMX_RELEASE_ASSERT(ic->vdwtype != evdwUSER || tabfn,
1497 "With VdW user tables we need a table file name");
1499 if (tabfn == nullptr)
1501 return std::unique_ptr<t_forcetable>(nullptr);
1504 t_forcetable *fullTable = make_tables(fp, ic, tabfn, rtab, 0);
1505 /* Copy the contents of the table to one that has just dispersion
1506 * and repulsion, to improve cache performance. We want the table
1507 * data to be aligned to 32-byte boundaries.
1509 std::unique_ptr<t_forcetable> dispersionCorrectionTable =
1510 std::make_unique<t_forcetable>(GMX_TABLE_INTERACTION_VDWREP_VDWDISP,
1511 fullTable->format);
1512 dispersionCorrectionTable->r = fullTable->r;
1513 dispersionCorrectionTable->n = fullTable->n;
1514 dispersionCorrectionTable->scale = fullTable->scale;
1515 dispersionCorrectionTable->formatsize = fullTable->formatsize;
1516 dispersionCorrectionTable->ninteractions = 2;
1517 dispersionCorrectionTable->stride = dispersionCorrectionTable->formatsize * dispersionCorrectionTable->ninteractions;
1518 snew_aligned(dispersionCorrectionTable->data, dispersionCorrectionTable->stride*(dispersionCorrectionTable->n+1), 32);
1520 for (int i = 0; i <= fullTable->n; i++)
1522 for (int j = 0; j < 8; j++)
1524 dispersionCorrectionTable->data[8*i+j] = fullTable->data[12*i+4+j];
1527 delete fullTable;
1529 return dispersionCorrectionTable;
1532 t_forcetable::t_forcetable(enum gmx_table_interaction interaction,
1533 enum gmx_table_format format) :
1534 interaction(interaction),
1535 format(format),
1536 r(0),
1537 n(0),
1538 scale(0),
1539 data(nullptr),
1540 formatsize(0),
1541 ninteractions(0),
1542 stride(0)
1546 t_forcetable::~t_forcetable()
1548 sfree_aligned(data);