Avoid numerical overflow with overlapping atoms
[gromacs.git] / src / gromacs / mdlib / nbnxn_kernels / nbnxn_kernel_ref.cpp
blobfe8d744083284b7f28c432e5c4bc832fe2c97b60
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013,2014,2015,2016, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
35 #include "gmxpre.h"
37 #include "nbnxn_kernel_ref.h"
39 #include "config.h"
41 #include <assert.h>
43 #include <cmath>
45 #include <algorithm>
47 #include "gromacs/math/functions.h"
48 #include "gromacs/math/vec.h"
49 #include "gromacs/mdlib/force.h"
50 #include "gromacs/mdlib/gmx_omp_nthreads.h"
51 #include "gromacs/mdlib/nb_verlet.h"
52 #include "gromacs/mdlib/nbnxn_consts.h"
53 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_common.h"
54 #include "gromacs/mdtypes/md_enums.h"
55 #include "gromacs/pbcutil/ishift.h"
56 #include "gromacs/utility/fatalerror.h"
57 #include "gromacs/utility/smalloc.h"
59 /*! \brief Typedefs for declaring lookup tables of kernel functions.
62 typedef void (*p_nbk_func_noener)(const nbnxn_pairlist_t *nbl,
63 const nbnxn_atomdata_t *nbat,
64 const interaction_const_t *ic,
65 rvec *shift_vec,
66 real *f,
67 real *fshift);
69 typedef void (*p_nbk_func_ener)(const nbnxn_pairlist_t *nbl,
70 const nbnxn_atomdata_t *nbat,
71 const interaction_const_t *ic,
72 rvec *shift_vec,
73 real *f,
74 real *fshift,
75 real *Vvdw,
76 real *Vc);
78 /* Analytical reaction-field kernels */
79 #define CALC_COUL_RF
80 #define LJ_CUT
81 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
82 #undef LJ_CUT
83 #define LJ_FORCE_SWITCH
84 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
85 #undef LJ_FORCE_SWITCH
86 #define LJ_POT_SWITCH
87 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
88 #undef LJ_POT_SWITCH
89 #define LJ_EWALD
90 #define LJ_CUT
91 #define LJ_EWALD_COMB_GEOM
92 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
93 #undef LJ_EWALD_COMB_GEOM
94 #define LJ_EWALD_COMB_LB
95 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
96 #undef LJ_EWALD_COMB_LB
97 #undef LJ_CUT
98 #undef LJ_EWALD
99 #undef CALC_COUL_RF
102 /* Tabulated exclusion interaction electrostatics kernels */
103 #define CALC_COUL_TAB
104 #define LJ_CUT
105 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
106 #undef LJ_CUT
107 #define LJ_FORCE_SWITCH
108 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
109 #undef LJ_FORCE_SWITCH
110 #define LJ_POT_SWITCH
111 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
112 #undef LJ_POT_SWITCH
113 #define LJ_EWALD
114 #define LJ_CUT
115 #define LJ_EWALD_COMB_GEOM
116 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
117 #undef LJ_EWALD_COMB_GEOM
118 #define LJ_EWALD_COMB_LB
119 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
120 #undef LJ_EWALD_COMB_LB
121 #undef LJ_CUT
122 #undef LJ_EWALD
123 /* Twin-range cut-off kernels */
124 #define VDW_CUTOFF_CHECK
125 #define LJ_CUT
126 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
127 #undef LJ_CUT
128 #define LJ_FORCE_SWITCH
129 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
130 #undef LJ_FORCE_SWITCH
131 #define LJ_POT_SWITCH
132 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
133 #undef LJ_POT_SWITCH
134 #define LJ_EWALD
135 #define LJ_CUT
136 #define LJ_EWALD_COMB_GEOM
137 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
138 #undef LJ_EWALD_COMB_GEOM
139 #define LJ_EWALD_COMB_LB
140 #include "gromacs/mdlib/nbnxn_kernels/nbnxn_kernel_ref_includes.h"
141 #undef LJ_EWALD_COMB_LB
142 #undef LJ_CUT
143 #undef LJ_EWALD
144 #undef VDW_CUTOFF_CHECK
145 #undef CALC_COUL_TAB
148 enum {
149 coultRF, coultTAB, coultTAB_TWIN, coultNR
152 enum {
153 vdwtCUT, vdwtFSWITCH, vdwtPSWITCH, vdwtEWALDGEOM, vdwtEWALDLB, vdwtNR
156 p_nbk_func_noener p_nbk_c_noener[coultNR][vdwtNR] =
158 { nbnxn_kernel_ElecRF_VdwLJ_F_ref, nbnxn_kernel_ElecRF_VdwLJFsw_F_ref, nbnxn_kernel_ElecRF_VdwLJPsw_F_ref, nbnxn_kernel_ElecRF_VdwLJEwCombGeom_F_ref, nbnxn_kernel_ElecRF_VdwLJEwCombLB_F_ref },
159 { nbnxn_kernel_ElecQSTab_VdwLJ_F_ref, nbnxn_kernel_ElecQSTab_VdwLJFsw_F_ref, nbnxn_kernel_ElecQSTab_VdwLJPsw_F_ref, nbnxn_kernel_ElecQSTab_VdwLJEwCombGeom_F_ref, nbnxn_kernel_ElecQSTab_VdwLJEwCombLB_F_ref },
160 { nbnxn_kernel_ElecQSTabTwinCut_VdwLJ_F_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJFsw_F_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJPsw_F_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_F_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJEwCombLB_F_ref }
163 p_nbk_func_ener p_nbk_c_ener[coultNR][vdwtNR] =
165 { nbnxn_kernel_ElecRF_VdwLJ_VF_ref, nbnxn_kernel_ElecRF_VdwLJFsw_VF_ref, nbnxn_kernel_ElecRF_VdwLJPsw_VF_ref, nbnxn_kernel_ElecRF_VdwLJEwCombGeom_VF_ref, nbnxn_kernel_ElecRF_VdwLJEwCombLB_VF_ref },
166 { nbnxn_kernel_ElecQSTab_VdwLJ_VF_ref, nbnxn_kernel_ElecQSTab_VdwLJFsw_VF_ref, nbnxn_kernel_ElecQSTab_VdwLJPsw_VF_ref, nbnxn_kernel_ElecQSTab_VdwLJEwCombGeom_VF_ref, nbnxn_kernel_ElecQSTab_VdwLJEwCombLB_VF_ref },
167 { nbnxn_kernel_ElecQSTabTwinCut_VdwLJ_VF_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJFsw_VF_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJPsw_VF_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_VF_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJEwCombLB_VF_ref }
170 p_nbk_func_ener p_nbk_c_energrp[coultNR][vdwtNR] =
172 { nbnxn_kernel_ElecRF_VdwLJ_VgrpF_ref, nbnxn_kernel_ElecRF_VdwLJFsw_VgrpF_ref, nbnxn_kernel_ElecRF_VdwLJPsw_VgrpF_ref, nbnxn_kernel_ElecRF_VdwLJEwCombGeom_VgrpF_ref, nbnxn_kernel_ElecRF_VdwLJEwCombLB_VgrpF_ref },
173 { nbnxn_kernel_ElecQSTab_VdwLJ_VgrpF_ref, nbnxn_kernel_ElecQSTab_VdwLJFsw_VgrpF_ref, nbnxn_kernel_ElecQSTab_VdwLJPsw_VgrpF_ref, nbnxn_kernel_ElecQSTab_VdwLJEwCombGeom_VgrpF_ref, nbnxn_kernel_ElecQSTab_VdwLJEwCombLB_VgrpF_ref },
174 { nbnxn_kernel_ElecQSTabTwinCut_VdwLJ_VgrpF_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJFsw_VgrpF_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJPsw_VgrpF_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJEwCombGeom_VgrpF_ref, nbnxn_kernel_ElecQSTabTwinCut_VdwLJEwCombLB_VgrpF_ref }
177 void
178 nbnxn_kernel_ref(const nbnxn_pairlist_set_t *nbl_list,
179 const nbnxn_atomdata_t *nbat,
180 const interaction_const_t *ic,
181 rvec *shift_vec,
182 int force_flags,
183 int clearF,
184 real *fshift,
185 real *Vc,
186 real *Vvdw)
188 int nnbl;
189 nbnxn_pairlist_t **nbl;
190 int coult;
191 int vdwt;
192 int nb;
193 int nthreads gmx_unused;
195 nnbl = nbl_list->nnbl;
196 nbl = nbl_list->nbl;
198 if (EEL_RF(ic->eeltype) || ic->eeltype == eelCUT)
200 coult = coultRF;
202 else
204 if (ic->rcoulomb == ic->rvdw)
206 coult = coultTAB;
208 else
210 coult = coultTAB_TWIN;
214 if (ic->vdwtype == evdwCUT)
216 switch (ic->vdw_modifier)
218 case eintmodPOTSHIFT:
219 case eintmodNONE:
220 vdwt = vdwtCUT;
221 break;
222 case eintmodFORCESWITCH:
223 vdwt = vdwtFSWITCH;
224 break;
225 case eintmodPOTSWITCH:
226 vdwt = vdwtPSWITCH;
227 break;
228 default:
229 gmx_incons("Unsupported VdW modifier");
230 break;
233 else if (ic->vdwtype == evdwPME)
235 if (ic->ljpme_comb_rule == ljcrGEOM)
237 assert(nbat->comb_rule == ljcrGEOM);
238 vdwt = vdwtEWALDGEOM;
240 else
242 assert(nbat->comb_rule == ljcrLB);
243 vdwt = vdwtEWALDLB;
246 else
248 gmx_incons("Unsupported vdwtype in nbnxn reference kernel");
251 // cppcheck-suppress unreadVariable
252 nthreads = gmx_omp_nthreads_get(emntNonbonded);
253 #pragma omp parallel for schedule(static) num_threads(nthreads)
254 for (nb = 0; nb < nnbl; nb++)
256 // Presently, the kernels do not call C++ code that can throw, so
257 // no need for a try/catch pair in this OpenMP region.
258 nbnxn_atomdata_output_t *out;
259 real *fshift_p;
261 out = &nbat->out[nb];
263 if (clearF == enbvClearFYes)
265 clear_f(nbat, nb, out->f);
268 if ((force_flags & GMX_FORCE_VIRIAL) && nnbl == 1)
270 fshift_p = fshift;
272 else
274 fshift_p = out->fshift;
276 if (clearF == enbvClearFYes)
278 clear_fshift(fshift_p);
282 if (!(force_flags & GMX_FORCE_ENERGY))
284 /* Don't calculate energies */
285 p_nbk_c_noener[coult][vdwt](nbl[nb], nbat,
287 shift_vec,
288 out->f,
289 fshift_p);
291 else if (out->nV == 1)
293 /* No energy groups */
294 out->Vvdw[0] = 0;
295 out->Vc[0] = 0;
297 p_nbk_c_ener[coult][vdwt](nbl[nb], nbat,
299 shift_vec,
300 out->f,
301 fshift_p,
302 out->Vvdw,
303 out->Vc);
305 else
307 /* Calculate energy group contributions */
308 int i;
310 for (i = 0; i < out->nV; i++)
312 out->Vvdw[i] = 0;
314 for (i = 0; i < out->nV; i++)
316 out->Vc[i] = 0;
319 p_nbk_c_energrp[coult][vdwt](nbl[nb], nbat,
321 shift_vec,
322 out->f,
323 fshift_p,
324 out->Vvdw,
325 out->Vc);
329 if (force_flags & GMX_FORCE_ENERGY)
331 reduce_energies_over_lists(nbat, nnbl, Vvdw, Vc);