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.
39 #include "forcetable.h"
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 */
85 /** Evaluates to true if the table type contains user data. */
86 #define ETAB_USER(e) ((e) == etabUSER || \
87 (e) == etabEwaldUser || (e) == etabEwaldUserSwitch)
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
] = {
99 { "LJ6Shift", FALSE
},
100 { "LJ12Shift", FALSE
},
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
},
126 double v_q_ewald_lr(double beta
, double r
)
130 return beta
*2/sqrt(M_PI
);
134 return std::erf(beta
*r
)/r
;
138 double v_lj_ewald_lr(double beta
, double r
)
140 double br
, br2
, br4
, r6
, factor
;
143 return gmx::power6(beta
)/6;
151 factor
= (1.0 - std::exp(-br2
)*(1 + br2
+ 0.5*br4
))/r6
;
156 EwaldCorrectionTables
157 generateEwaldCorrectionTables(const int numPoints
,
158 const double tableScaling
,
160 real_space_grid_contribution_computer v_lr
)
165 gmx_bool bOutOfRange
;
166 double v_r0
, v_r1
, v_inrange
, vi
, a0
, a1
, a2dx
;
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.
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.
202 i_inrange
= numPoints
;
205 for (i
= numPoints
- 1; i
>= 0; i
--)
209 v_r0
= (*v_lr
)(beta
, x_r0
);
220 /* Linear continuation for the last point in range */
221 vi
= v_inrange
- dc
*(i
- i_inrange
)*dx
;
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
)
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 */
259 /* tab[i] will contain the average of the splines over the two intervals */
260 table_f
[i
] += -0.5*dc
;
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.
271 a2dx
= (a1
*dx
+ v_r1
- a0
)*2/dx
;
273 /* Set dc to the derivative at the next point */
276 if (dc_new
!= dc_new
|| dc_new
< -tab_max
|| dc_new
> tab_max
)
286 table_f
[(i
-1)] = -0.5*dc
;
288 /* Currently the last value only contains half the force: double it */
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;
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
,
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");
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)''' */
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
);
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)))''' */
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
);
393 fprintf(debug
, "Ewald LJ quadratic spline table spacing: %f nm\n", 1/sc_lj
);
396 sc
= std::max(sc
, sc_lj
);
402 static void copy2table(int n
, int offset
, int stride
,
403 const double x
[], const double Vtab
[], const double Ftab
[], real scalefactor
,
406 /* Use double prec. for the intermediary variables
407 * and temporary x/vtab/vtab2 data to avoid unnecessary
414 for (i
= 0; (i
< n
); i
++)
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
;
425 /* Fill the last entry with a linear potential,
426 * this is mainly for rounding issues with angle and dihedral potentials.
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
)
445 td
->tabscale
= tabscale
;
454 static void spline_forces(int nx
, double h
, const double v
[], gmx_bool bS3
, gmx_bool bE3
,
458 double v3
, b_s
, b_e
, b
;
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.
475 /* Fit V''' at the start */
476 v3
= v
[3] - 3*v
[2] + 3*v
[1] - v
[0];
479 fprintf(debug
, "The left third derivative is %g\n", v3
/(h
*h
*h
));
481 b_s
= 2*(v
[1] - v
[0]) + v3
/6;
486 /* Fit V'' at the start */
489 v2
= -v
[3] + 4*v
[2] - 5*v
[1] + 2*v
[0];
490 /* v2 = v[2] - 2*v[1] + v[0]; */
493 fprintf(debug
, "The left second derivative is %g\n", v2
/(h
*h
));
495 b_s
= 3*(v
[1] - v
[0]) - v2
/2;
501 b_s
= 3*(v
[2] - v
[0]) + f
[0]*h
;
506 /* Fit V''' at the end */
507 v3
= v
[nx
-1] - 3*v
[nx
-2] + 3*v
[nx
-3] - v
[nx
-4];
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;
517 /* V'=0 at the end */
518 b_e
= 3*(v
[nx
-1] - v
[nx
-3]) + f
[nx
-1]*h
;
523 beta
= (bS3
? 1 : 4);
525 /* For V'' fitting */
526 /* beta = (bS3 ? 2 : 4); */
529 for (i
= start
+1; i
< end
; 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];
546 /* Correct for the minus sign and the spacing */
547 for (i
= start
; i
< end
; i
++)
553 static void set_forces(FILE *fp
, int angle
,
554 int nx
, double h
, double v
[], double f
[],
562 "Force generation for dihedral tables is not (yet) implemented");
566 while (v
[start
] == 0)
572 while (v
[end
-1] == 0)
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
[])
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
;
603 std::string libfn
= gmx::findLibraryFile(filename
);
604 nx
= read_xvg(libfn
.c_str(), &yy
, &ny
);
607 gmx_fatal(FARGS
, "Trying to read file %s, but nr columns = %d, should be %d",
608 libfn
.c_str(), ny
, nny
);
615 "The first distance in file %s is %f nm instead of %f nm",
616 libfn
.c_str(), yy
[0][0], 0.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]);
641 fprintf(fp
, "Read user tables from %s with %d data points.\n", libfn
.c_str(), nx
);
644 fprintf(fp
, "Tabscale = %g points/nm\n", tabscale
);
649 for (k
= 0; k
< ntab
; k
++)
653 for (i
= 0; (i
< nx
); i
++)
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)
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)
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
);
703 /* Check if the second column is close to minus the numerical
704 * derivative of the first column.
708 for (i
= 1; (i
< nx
-1); i
++)
713 if (vm
!= 0 && vp
!= 0 && f
!= 0)
715 /* Take the centered difference */
716 numf
= -(vp
- vm
)*0.5*tabscale
;
719 ssd
+= fabs(2*(f
- numf
)/(f
+ numf
));
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
));
732 fprintf(debug
, "%s", buf
);
738 fprintf(fp
, "\nWARNING: %s\n", buf
);
740 fprintf(stderr
, "\nWARNING: %s\n", buf
);
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
++)
767 static void done_tabledata(t_tabledata
*td
)
779 static void fill_table(t_tabledata
*td
, int tp
, const interaction_const_t
*ic
,
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.
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
;
809 bPotentialSwitch
= FALSE
;
810 bForceSwitch
= FALSE
;
811 bPotentialShift
= FALSE
;
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
) ||
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
)));
830 if (tprops
[tp
].bCoulomb
)
832 r1
= ic
->rcoulomb_switch
;
837 r1
= ic
->rvdw_switch
;
840 if (bPotentialSwitch
)
842 ksw
= 1.0/(gmx::power5(rc
-r1
));
854 else if (tp
== etabLJ6Shift
)
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
)
877 fprintf(debug
, "Setting up tables\n"); fflush(debug
);
883 rc6
= 1.0/(rc2
*rc2
*rc2
);
884 if (gmx_within_tol(reppow
, 12.0, 10*GMX_DOUBLE_EPS
))
890 rc12
= std::pow(rc
, -reppow
);
900 Vcut
= -rc6
*exp(-ewclj
*ewclj
*rc2
)*(1 + ewclj
*ewclj
*rc2
+ gmx::power4(ewclj
)*rc2
*rc2
/2);
910 case etabEwaldSwitch
:
911 Vcut
= std::erfc(ewc
*rc
)/rc
;
914 /* Only calculate minus the reciprocal space contribution */
915 Vcut
= -std::erf(ewc
*rc
)/rc
;
919 /* No need for preventing the usage of modifiers with RF */
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
++)
940 if (gmx_within_tol(reppow
, 12.0, 10*GMX_DOUBLE_EPS
))
946 r12
= std::pow(r
, -reppow
);
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
956 * ksw is just the constant 1/(rc-r1)^5, to save some calculations...
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... */
1005 Ftab
= reppow
*Vtab
/r
;
1007 case etabLJ12Switch
:
1013 Ftab
= reppow
*Vtab
/r
;
1019 Vtab
= -(r6
-6.0*(rc
-r
)*rc6
/rc
-rc6
);
1020 Ftab
= -(6.0*r6
/r
-6.0*rc6
/rc
);
1031 Vtab
= -(r6
-6.0*(rc
-r
)*rc6
/rc
-rc6
);
1032 Ftab
= -(6.0*r6
/r
-6.0*rc6
/rc
);
1044 case etabCOULSwitch
:
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
;
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
;
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
;
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
)
1085 Vtab
= 1.0/r
-(rc
-r
)/(rc
*rc
)-1.0/rc
;
1086 Ftab
= 1.0/r2
-1.0/(rc
*rc
);
1095 gmx_fatal(FARGS
, "Table type %d not implemented yet. (%s,%d)",
1096 tp
, __FILE__
, __LINE__
);
1100 /* Normal coulomb with cut-off correction for potential */
1104 /* If in Shifting range add something to it */
1107 r12
= (r
-r1
)*(r
-r1
);
1109 Vtab
+= -A_3
*r13
- B_4
*r12
*r12
;
1110 Ftab
+= A
*r12
+ B
*r13
;
1115 /* Make sure interactions are zero outside cutoff with modifiers */
1120 if (bPotentialShift
)
1128 /* Make sure interactions are zero outside cutoff with modifiers */
1140 if (bPotentialSwitch
)
1144 /* Make sure interactions are zero outside cutoff with modifiers */
1150 Ftab
= Ftab
*swi
- Vtab
*swi1
;
1154 /* Convert to single precision when we store to mem */
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.
1180 switch (ic
->eeltype
)
1184 case eelPMEUSERSWITCH
:
1193 eltype
= ic
->eeltype
;
1199 tabsel
[etiCOUL
] = etabCOUL
;
1202 tabsel
[etiCOUL
] = etabShift
;
1205 if (ic
->rcoulomb
> ic
->rcoulomb_switch
)
1207 tabsel
[etiCOUL
] = etabShift
;
1211 tabsel
[etiCOUL
] = etabCOUL
;
1217 tabsel
[etiCOUL
] = etabEwald
;
1220 tabsel
[etiCOUL
] = etabEwaldSwitch
;
1223 tabsel
[etiCOUL
] = etabEwaldUser
;
1225 case eelPMEUSERSWITCH
:
1226 tabsel
[etiCOUL
] = etabEwaldUserSwitch
;
1230 tabsel
[etiCOUL
] = etabRF_ZERO
;
1233 tabsel
[etiCOUL
] = etabCOULSwitch
;
1236 tabsel
[etiCOUL
] = etabUSER
;
1239 tabsel
[etiCOUL
] = etabCOULEncad
;
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
;
1253 if (b14only
&& ic
->vdwtype
!= evdwUSER
)
1259 vdwtype
= ic
->vdwtype
;
1265 tabsel
[etiLJ6
] = etabLJ6Switch
;
1266 tabsel
[etiLJ12
] = etabLJ12Switch
;
1269 tabsel
[etiLJ6
] = etabLJ6Shift
;
1270 tabsel
[etiLJ12
] = etabLJ12Shift
;
1273 tabsel
[etiLJ6
] = etabUSER
;
1274 tabsel
[etiLJ12
] = etabUSER
;
1277 tabsel
[etiLJ6
] = etabLJ6
;
1278 tabsel
[etiLJ12
] = etabLJ12
;
1280 case evdwENCADSHIFT
:
1281 tabsel
[etiLJ6
] = etabLJ6Encad
;
1282 tabsel
[etiLJ12
] = etabLJ12Encad
;
1285 tabsel
[etiLJ6
] = etabLJ6Ewald
;
1286 tabsel
[etiLJ12
] = etabLJ12
;
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
)
1309 case eintmodPOTSHIFT
:
1310 case eintmodEXACTCUTOFF
:
1311 /* No modification */
1313 case eintmodPOTSWITCH
:
1314 tabsel
[etiLJ6
] = etabLJ6Switch
;
1315 tabsel
[etiLJ12
] = etabLJ12Switch
;
1317 case eintmodFORCESWITCH
:
1318 tabsel
[etiLJ6
] = etabLJ6Shift
;
1319 tabsel
[etiLJ12
] = etabLJ12Shift
;
1322 gmx_incons("Unsupported vdw_modifier");
1329 t_forcetable
*make_tables(FILE *out
,
1330 const interaction_const_t
*ic
,
1332 real rtab
, int flags
)
1335 gmx_bool b14only
, useUserTable
;
1336 int nx0
, tabsel
[etiNR
];
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
;
1352 set_table_type(tabsel
, ic
, b14only
);
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
;
1374 read_tables(out
, fn
, etiNR
, 0, td
);
1375 if (rtab
== 0 || (flags
& GMX_MAKETABLES_14ONLY
))
1377 table
->n
= td
[0].nx
;
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
;
1393 // No tables are read
1395 table
->scale
= 2000.0;
1397 table
->scale
= 500.0;
1399 table
->n
= static_cast<int>(rtab
*table
->scale
);
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
);
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
,
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.
1443 scalefactor
= 1.0/6.0;
1445 else if (k
== etiLJ12
&& tabsel
[k
] != etabEXPMIN
)
1447 scalefactor
= 1.0/12.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
]));
1463 bondedtable_t
make_bonded_table(FILE *fplog
, const char *fn
, int angle
)
1470 read_tables(fplog
, fn
, 1, angle
, &td
);
1473 /* Convert the table from degrees to radians */
1474 for (i
= 0; i
< td
.nx
; i
++)
1479 td
.tabscale
*= RAD2DEG
;
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
);
1490 std::unique_ptr
<t_forcetable
>
1491 makeDispersionCorrectionTable(FILE *fp
,
1492 const interaction_const_t
*ic
,
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
,
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
];
1529 return dispersionCorrectionTable
;
1532 t_forcetable::t_forcetable(enum gmx_table_interaction interaction
,
1533 enum gmx_table_format format
) :
1534 interaction(interaction
),
1546 t_forcetable::~t_forcetable()
1548 sfree_aligned(data
);