Apply clang-format to source tree
[alexxy/gromacs.git] / src / gromacs / nbnxm / kernels_reference / kernel_ref_inner.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014,2015,2016,2018,2019, 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.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35
36 /* When calculating RF or Ewald interactions we calculate the electrostatic
37  * forces and energies on excluded atom pairs here in the non-bonded loops.
38  */
39 #if defined CHECK_EXCLS && (defined CALC_COULOMB || defined LJ_EWALD)
40 #    define EXCL_FORCES
41 #endif
42
43 {
44     int cj;
45 #ifdef ENERGY_GROUPS
46     int egp_cj;
47 #endif
48     int i;
49
50     cj = l_cj[cjind].cj;
51
52 #ifdef ENERGY_GROUPS
53     egp_cj = nbatParams.energrp[cj];
54 #endif
55     for (i = 0; i < UNROLLI; i++)
56     {
57         int ai;
58         int type_i_off;
59         int j;
60
61         ai = ci * UNROLLI + i;
62
63         type_i_off = type[ai] * ntype2;
64
65         for (j = 0; j < UNROLLJ; j++)
66         {
67             int  aj;
68             real dx, dy, dz;
69             real rsq, rinv;
70             real rinvsq, rinvsix;
71             real c6, c12;
72             real FrLJ6 = 0, FrLJ12 = 0, frLJ = 0;
73             real VLJ gmx_unused;
74 #if defined LJ_FORCE_SWITCH || defined LJ_POT_SWITCH
75             real r, rsw;
76 #endif
77
78 #ifdef CALC_COULOMB
79             real qq;
80             real fcoul;
81 #    ifdef CALC_COUL_TAB
82             real rs, frac;
83             int  ri;
84             real fexcl;
85 #    endif
86 #    ifdef CALC_ENERGIES
87             real vcoul;
88 #    endif
89 #endif
90             real fscal;
91             real fx, fy, fz;
92
93             /* A multiply mask used to zero an interaction
94              * when either the distance cutoff is exceeded, or
95              * (if appropriate) the i and j indices are
96              * unsuitable for this kind of inner loop. */
97             real skipmask;
98
99 #ifdef CHECK_EXCLS
100             /* A multiply mask used to zero an interaction
101              * when that interaction should be excluded
102              * (e.g. because of bonding). */
103             real interact = static_cast<real>((l_cj[cjind].excl >> (i * UNROLLI + j)) & 1);
104 #    ifndef EXCL_FORCES
105             skipmask = interact;
106 #    else
107             skipmask = (cj == ci_sh && j <= i) ? 0.0 : 1.0;
108 #    endif
109 #else
110             constexpr real interact = 1.0;
111             skipmask                = interact;
112 #endif
113
114             VLJ = 0;
115
116             aj = cj * UNROLLJ + j;
117
118             dx = xi[i * XI_STRIDE + XX] - x[aj * X_STRIDE + XX];
119             dy = xi[i * XI_STRIDE + YY] - x[aj * X_STRIDE + YY];
120             dz = xi[i * XI_STRIDE + ZZ] - x[aj * X_STRIDE + ZZ];
121
122             rsq = dx * dx + dy * dy + dz * dz;
123
124             /* Prepare to enforce the cut-off. */
125             skipmask = (rsq >= rcut2) ? 0 : skipmask;
126             /* 9 flops for r^2 + cut-off check */
127
128             // Ensure the distances do not fall below the limit where r^-12 overflows.
129             // This should never happen for normal interactions.
130             rsq = std::max(rsq, NBNXN_MIN_RSQ);
131
132 #ifdef COUNT_PAIRS
133             npair++;
134 #endif
135
136             rinv = gmx::invsqrt(rsq);
137             /* 5 flops for invsqrt */
138
139             /* Partially enforce the cut-off (and perhaps
140              * exclusions) to avoid possible overflow of
141              * rinvsix when computing LJ, and/or overflowing
142              * the Coulomb table during lookup. */
143             rinv = rinv * skipmask;
144
145             rinvsq = rinv * rinv;
146
147 #ifdef HALF_LJ
148             if (i < UNROLLI / 2)
149 #endif
150             {
151                 c6  = nbfp[type_i_off + type[aj] * 2];
152                 c12 = nbfp[type_i_off + type[aj] * 2 + 1];
153
154 #if defined LJ_CUT || defined LJ_FORCE_SWITCH || defined LJ_POT_SWITCH
155                 rinvsix = interact * rinvsq * rinvsq * rinvsq;
156                 FrLJ6   = c6 * rinvsix;
157                 FrLJ12  = c12 * rinvsix * rinvsix;
158                 frLJ    = FrLJ12 - FrLJ6;
159                 /* 7 flops for r^-2 + LJ force */
160 #    if defined CALC_ENERGIES || defined LJ_POT_SWITCH
161                 VLJ = (FrLJ12 + c12 * ic->repulsion_shift.cpot) / 12
162                       - (FrLJ6 + c6 * ic->dispersion_shift.cpot) / 6;
163                 /* 7 flops for LJ energy */
164 #    endif
165 #endif
166
167 #if defined LJ_FORCE_SWITCH || defined LJ_POT_SWITCH
168                 /* Force or potential switching from ic->rvdw_switch */
169                 r   = rsq * rinv;
170                 rsw = r - ic->rvdw_switch;
171                 rsw = (rsw >= 0.0 ? rsw : 0.0);
172 #endif
173 #ifdef LJ_FORCE_SWITCH
174                 frLJ += -c6 * (ic->dispersion_shift.c2 + ic->dispersion_shift.c3 * rsw) * rsw * rsw * r
175                         + c12 * (ic->repulsion_shift.c2 + ic->repulsion_shift.c3 * rsw) * rsw * rsw * r;
176 #    if defined CALC_ENERGIES
177                 VLJ += -c6 * (-ic->dispersion_shift.c2 / 3 - ic->dispersion_shift.c3 / 4 * rsw)
178                                * rsw * rsw * rsw
179                        + c12 * (-ic->repulsion_shift.c2 / 3 - ic->repulsion_shift.c3 / 4 * rsw)
180                                  * rsw * rsw * rsw;
181 #    endif
182 #endif
183
184 #if defined CALC_ENERGIES || defined LJ_POT_SWITCH
185                 /* Masking should be done after force switching,
186                  * but before potential switching.
187                  */
188                 /* Need to zero the interaction if there should be exclusion. */
189                 VLJ = VLJ * interact;
190 #endif
191
192 #ifdef LJ_POT_SWITCH
193                 {
194                     real sw, dsw;
195
196                     sw  = 1.0 + (swV3 + (swV4 + swV5 * rsw) * rsw) * rsw * rsw * rsw;
197                     dsw = (swF2 + (swF3 + swF4 * rsw) * rsw) * rsw * rsw;
198
199                     frLJ = frLJ * sw - r * VLJ * dsw;
200                     VLJ *= sw;
201                 }
202 #endif
203
204 #ifdef LJ_EWALD
205                 {
206                     real c6grid, rinvsix_nm, cr2, expmcr2, poly;
207 #    ifdef CALC_ENERGIES
208                     real sh_mask;
209 #    endif
210
211 #    ifdef LJ_EWALD_COMB_GEOM
212                     c6grid = ljc[type[ai] * 2] * ljc[type[aj] * 2];
213 #    elif defined LJ_EWALD_COMB_LB
214                     {
215                         real sigma, sigma2, epsilon;
216
217                         /* These sigma and epsilon are scaled to give 6*C6 */
218                         sigma   = ljc[type[ai] * 2] + ljc[type[aj] * 2];
219                         epsilon = ljc[type[ai] * 2 + 1] * ljc[type[aj] * 2 + 1];
220
221                         sigma2 = sigma * sigma;
222                         c6grid = epsilon * sigma2 * sigma2 * sigma2;
223                     }
224 #    else
225 #        error "No LJ Ewald combination rule defined"
226 #    endif
227
228 #    ifdef CHECK_EXCLS
229                     /* Recalculate rinvsix without exclusion mask */
230                     rinvsix_nm = rinvsq * rinvsq * rinvsq;
231 #    else
232                     rinvsix_nm = rinvsix;
233 #    endif
234                     cr2 = lje_coeff2 * rsq;
235 #    if GMX_DOUBLE
236                     expmcr2 = exp(-cr2);
237 #    else
238                     expmcr2    = expf(-cr2);
239 #    endif
240                     poly = 1 + cr2 + 0.5 * cr2 * cr2;
241
242                     /* Subtract the grid force from the total LJ force */
243                     frLJ += c6grid * (rinvsix_nm - expmcr2 * (rinvsix_nm * poly + lje_coeff6_6));
244 #    ifdef CALC_ENERGIES
245                     /* Shift should only be applied to real LJ pairs */
246                     sh_mask = lje_vc * interact;
247
248                     VLJ += c6grid / 6 * (rinvsix_nm * (1 - expmcr2 * poly) + sh_mask);
249 #    endif
250                 }
251 #endif /* LJ_EWALD */
252
253 #ifdef VDW_CUTOFF_CHECK
254                 /* Mask for VdW cut-off shorter than Coulomb cut-off */
255                 {
256                     real skipmask_rvdw;
257
258                     skipmask_rvdw = (rsq < rvdw2) ? 1.0 : 0.0;
259                     frLJ *= skipmask_rvdw;
260 #    ifdef CALC_ENERGIES
261                     VLJ *= skipmask_rvdw;
262 #    endif
263                 }
264 #else
265 #    if defined CALC_ENERGIES
266                 /* Need to zero the interaction if r >= rcut */
267                 VLJ = VLJ * skipmask;
268                 /* 1 more flop for LJ energy */
269 #    endif
270 #endif /* VDW_CUTOFF_CHECK */
271
272
273 #ifdef CALC_ENERGIES
274 #    ifdef ENERGY_GROUPS
275                 Vvdw[egp_sh_i[i] + ((egp_cj >> (nbatParams.neg_2log * j)) & egp_mask)] += VLJ;
276 #    else
277                 Vvdw_ci += VLJ;
278                 /* 1 flop for LJ energy addition */
279 #    endif
280 #endif
281             }
282
283 #ifdef CALC_COULOMB
284             /* Enforce the cut-off and perhaps exclusions. In
285              * those cases, rinv is zero because of skipmask,
286              * but fcoul and vcoul will later be non-zero (in
287              * both RF and table cases) because of the
288              * contributions that do not depend on rinv. These
289              * contributions cannot be allowed to accumulate
290              * to the force and potential, and the easiest way
291              * to do this is to zero the charges in
292              * advance. */
293             qq = skipmask * qi[i] * q[aj];
294
295 #    ifdef CALC_COUL_RF
296             fcoul = qq * (interact * rinv * rinvsq - k_rf2);
297             /* 4 flops for RF force */
298 #        ifdef CALC_ENERGIES
299             vcoul = qq * (interact * rinv + k_rf * rsq - c_rf);
300             /* 4 flops for RF energy */
301 #        endif
302 #    endif
303
304 #    ifdef CALC_COUL_TAB
305             rs   = rsq * rinv * tab_coul_scale;
306             ri   = int(rs);
307             frac = rs - static_cast<real>(ri);
308 #        if !GMX_DOUBLE
309             /* fexcl = F_i + frac * (F_(i+1)-F_i) */
310             fexcl = tab_coul_FDV0[ri * 4] + frac * tab_coul_FDV0[ri * 4 + 1];
311 #        else
312             /* fexcl = (1-frac) * F_i + frac * F_(i+1) */
313             fexcl = (1 - frac) * tab_coul_F[ri] + frac * tab_coul_F[ri + 1];
314 #        endif
315             fcoul = interact * rinvsq - fexcl;
316             /* 7 flops for float 1/r-table force */
317 #        ifdef CALC_ENERGIES
318 #            if !GMX_DOUBLE
319             vcoul = qq
320                     * (interact * (rinv - ic->sh_ewald)
321                        - (tab_coul_FDV0[ri * 4 + 2] - halfsp * frac * (tab_coul_FDV0[ri * 4] + fexcl)));
322             /* 7 flops for float 1/r-table energy (8 with excls) */
323 #            else
324             vcoul = qq
325                     * (interact * (rinv - ic->sh_ewald)
326                        - (tab_coul_V[ri] - halfsp * frac * (tab_coul_F[ri] + fexcl)));
327 #            endif
328 #        endif
329             fcoul *= qq * rinv;
330 #    endif
331
332 #    ifdef CALC_ENERGIES
333 #        ifdef ENERGY_GROUPS
334             Vc[egp_sh_i[i] + ((egp_cj >> (nbatParams.neg_2log * j)) & egp_mask)] += vcoul;
335 #        else
336             Vc_ci += vcoul;
337             /* 1 flop for Coulomb energy addition */
338 #        endif
339 #    endif
340 #endif
341
342 #ifdef CALC_COULOMB
343 #    ifdef HALF_LJ
344             if (i < UNROLLI / 2)
345 #    endif
346             {
347                 fscal = frLJ * rinvsq + fcoul;
348                 /* 2 flops for scalar LJ+Coulomb force */
349             }
350 #    ifdef HALF_LJ
351             else
352             {
353                 fscal = fcoul;
354             }
355 #    endif
356 #else
357             fscal = frLJ * rinvsq;
358 #endif
359             fx = fscal * dx;
360             fy = fscal * dy;
361             fz = fscal * dz;
362
363             /* Increment i-atom force */
364             fi[i * FI_STRIDE + XX] += fx;
365             fi[i * FI_STRIDE + YY] += fy;
366             fi[i * FI_STRIDE + ZZ] += fz;
367             /* Decrement j-atom force */
368             f[aj * F_STRIDE + XX] -= fx;
369             f[aj * F_STRIDE + YY] -= fy;
370             f[aj * F_STRIDE + ZZ] -= fz;
371             /* 9 flops for force addition */
372         }
373     }
374 }
375
376 #undef interact
377 #undef EXCL_FORCES