Move nbnxn files to nbnxm directory
[alexxy/gromacs.git] / src / gromacs / nbnxm / kernels_reference / kernel_ref_outer.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014,2015,2017,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 #define UNROLLI    4
37 #define UNROLLJ    4
38
39 static_assert(UNROLLI == c_nbnxnCpuIClusterSize, "UNROLLI should match the i-cluster size");
40
41 /* We could use nbat->xstride and nbat->fstride, but macros might be faster */
42 #define X_STRIDE   3
43 #define F_STRIDE   3
44 /* Local i-atom buffer strides */
45 #define XI_STRIDE  3
46 #define FI_STRIDE  3
47
48
49 /* All functionality defines are set here, except for:
50  * CALC_ENERGIES, ENERGY_GROUPS which are defined before.
51  * CHECK_EXCLS, which is set just before including the inner loop contents.
52  */
53
54 /* We always calculate shift forces, because it's cheap anyhow */
55 #define CALC_SHIFTFORCES
56
57 #ifdef CALC_COUL_RF
58 #define NBK_FUNC_NAME2(ljt, feg) nbnxn_kernel ## _ElecRF ## ljt ## feg ## _ref
59 #endif
60 #ifdef CALC_COUL_TAB
61 #ifndef VDW_CUTOFF_CHECK
62 #define NBK_FUNC_NAME2(ljt, feg) nbnxn_kernel ## _ElecQSTab ## ljt ## feg ## _ref
63 #else
64 #define NBK_FUNC_NAME2(ljt, feg) nbnxn_kernel ## _ElecQSTabTwinCut ## ljt ## feg ## _ref
65 #endif
66 #endif
67
68 #if defined LJ_CUT && !defined LJ_EWALD
69 #define NBK_FUNC_NAME(feg) NBK_FUNC_NAME2(_VdwLJ, feg)
70 #elif defined LJ_FORCE_SWITCH
71 #define NBK_FUNC_NAME(feg) NBK_FUNC_NAME2(_VdwLJFsw, feg)
72 #elif defined LJ_POT_SWITCH
73 #define NBK_FUNC_NAME(feg) NBK_FUNC_NAME2(_VdwLJPsw, feg)
74 #elif defined LJ_EWALD
75 #ifdef LJ_EWALD_COMB_GEOM
76 #define NBK_FUNC_NAME(feg) NBK_FUNC_NAME2(_VdwLJEwCombGeom, feg)
77 #else
78 #define NBK_FUNC_NAME(feg) NBK_FUNC_NAME2(_VdwLJEwCombLB, feg)
79 #endif
80 #else
81 #error "No VdW type defined"
82 #endif
83
84 void
85 #ifndef CALC_ENERGIES
86 NBK_FUNC_NAME(_F)     // NOLINT(misc-definitions-in-headers)
87 #else
88 #ifndef ENERGY_GROUPS
89 NBK_FUNC_NAME(_VF)    // NOLINT(misc-definitions-in-headers)
90 #else
91 NBK_FUNC_NAME(_VgrpF) // NOLINT(misc-definitions-in-headers)
92 #endif
93 #endif
94 #undef NBK_FUNC_NAME
95 #undef NBK_FUNC_NAME2
96 (const NbnxnPairlistCpu     *nbl,
97  const nbnxn_atomdata_t     *nbat,
98  const interaction_const_t  *ic,
99  rvec                       *shift_vec,
100  real                       *f,
101  real gmx_unused            *fshift
102 #ifdef CALC_ENERGIES
103  ,
104  real                       *Vvdw,
105  real                       *Vc
106 #endif
107 )
108 {
109     const nbnxn_cj_t   *l_cj;
110     real                rcut2;
111 #ifdef VDW_CUTOFF_CHECK
112     real                rvdw2;
113 #endif
114     int                 ntype2;
115     real                facel;
116     int                 ci, ci_sh;
117     int                 ish, ishf;
118     gmx_bool            do_LJ, half_LJ, do_coul;
119     int                 cjind0, cjind1, cjind;
120
121     real                xi[UNROLLI*XI_STRIDE];
122     real                fi[UNROLLI*FI_STRIDE];
123     real                qi[UNROLLI];
124
125 #ifdef CALC_ENERGIES
126 #ifndef ENERGY_GROUPS
127
128     real       Vvdw_ci, Vc_ci;
129 #else
130     int        egp_mask;
131     int        egp_sh_i[UNROLLI];
132 #endif
133 #endif
134 #ifdef LJ_POT_SWITCH
135     real       swV3, swV4, swV5;
136     real       swF2, swF3, swF4;
137 #endif
138 #ifdef LJ_EWALD
139     real        lje_coeff2, lje_coeff6_6;
140 #ifdef CALC_ENERGIES
141     real        lje_vc;
142 #endif
143 #endif
144
145 #ifdef CALC_COUL_RF
146     real       k_rf2;
147 #ifdef CALC_ENERGIES
148     real       k_rf, c_rf;
149 #endif
150 #endif
151 #ifdef CALC_COUL_TAB
152 #ifdef CALC_ENERGIES
153     real       halfsp;
154 #endif
155 #if !GMX_DOUBLE
156     const real            *tab_coul_FDV0;
157 #else
158     const real            *tab_coul_F;
159     const real gmx_unused *tab_coul_V;
160 #endif
161 #endif
162
163 #ifdef COUNT_PAIRS
164     int npair = 0;
165 #endif
166
167 #ifdef LJ_POT_SWITCH
168     swV3 = ic->vdw_switch.c3;
169     swV4 = ic->vdw_switch.c4;
170     swV5 = ic->vdw_switch.c5;
171     swF2 = 3*ic->vdw_switch.c3;
172     swF3 = 4*ic->vdw_switch.c4;
173     swF4 = 5*ic->vdw_switch.c5;
174 #endif
175
176     const nbnxn_atomdata_t::Params &nbatParams = nbat->params();
177
178 #ifdef LJ_EWALD
179     lje_coeff2   = ic->ewaldcoeff_lj*ic->ewaldcoeff_lj;
180     lje_coeff6_6 = lje_coeff2*lje_coeff2*lje_coeff2/6.0;
181 #ifdef CALC_ENERGIES
182     lje_vc       = ic->sh_lj_ewald;
183 #endif
184
185     const real *ljc = nbatParams.nbfp_comb.data();
186 #endif
187
188 #ifdef CALC_COUL_RF
189     k_rf2 = 2*ic->k_rf;
190 #ifdef CALC_ENERGIES
191     k_rf = ic->k_rf;
192     c_rf = ic->c_rf;
193 #endif
194 #endif
195 #ifdef CALC_COUL_TAB
196 #ifdef CALC_ENERGIES
197     halfsp = 0.5/ic->tabq_scale;
198 #endif
199
200 #if !GMX_DOUBLE
201     tab_coul_FDV0 = ic->tabq_coul_FDV0;
202 #else
203     tab_coul_F    = ic->tabq_coul_F;
204     tab_coul_V    = ic->tabq_coul_V;
205 #endif
206 #endif
207
208 #ifdef ENERGY_GROUPS
209     egp_mask = (1 << nbatParams.neg_2log) - 1;
210 #endif
211
212
213     rcut2                = ic->rcoulomb*ic->rcoulomb;
214 #ifdef VDW_CUTOFF_CHECK
215     rvdw2                = ic->rvdw*ic->rvdw;
216 #endif
217
218     ntype2               = nbatParams.numTypes*2;
219     const real *nbfp     = nbatParams.nbfp.data();
220     const real *q        = nbatParams.q.data();
221     const int  *type     = nbatParams.type.data();
222     facel                = ic->epsfac;
223     const real *shiftvec = shift_vec[0];
224     const real *x        = nbat->x().data();
225
226     l_cj = nbl->cj.data();
227
228     for (const nbnxn_ci_t &ciEntry : nbl->ci)
229     {
230         int i, d;
231
232         ish              = (ciEntry.shift & NBNXN_CI_SHIFT);
233         /* x, f and fshift are assumed to be stored with stride 3 */
234         ishf             = ish*DIM;
235         cjind0           = ciEntry.cj_ind_start;
236         cjind1           = ciEntry.cj_ind_end;
237         /* Currently only works super-cells equal to sub-cells */
238         ci               = ciEntry.ci;
239         ci_sh            = (ish == CENTRAL ? ci : -1);
240
241         /* We have 5 LJ/C combinations, but use only three inner loops,
242          * as the other combinations are unlikely and/or not much faster:
243          * inner half-LJ + C for half-LJ + C / no-LJ + C
244          * inner LJ + C      for full-LJ + C
245          * inner LJ          for full-LJ + no-C / half-LJ + no-C
246          */
247         do_LJ   = ((ciEntry.shift & NBNXN_CI_DO_LJ(0)) != 0);
248         do_coul = ((ciEntry.shift & NBNXN_CI_DO_COUL(0)) != 0);
249         half_LJ = (((ciEntry.shift & NBNXN_CI_HALF_LJ(0)) != 0) || !do_LJ) && do_coul;
250 #ifdef CALC_ENERGIES
251
252 #ifdef LJ_EWALD
253         gmx_bool do_self = TRUE;
254 #else
255         gmx_bool do_self = do_coul;
256 #endif
257
258 #ifndef ENERGY_GROUPS
259         Vvdw_ci = 0;
260         Vc_ci   = 0;
261 #else
262         for (i = 0; i < UNROLLI; i++)
263         {
264             egp_sh_i[i] = ((nbatParams.energrp[ci] >> (i*nbatParams.neg_2log)) & egp_mask)*nbatParams.nenergrp;
265         }
266 #endif
267 #endif
268
269         for (i = 0; i < UNROLLI; i++)
270         {
271             for (d = 0; d < DIM; d++)
272             {
273                 xi[i*XI_STRIDE+d] = x[(ci*UNROLLI+i)*X_STRIDE+d] + shiftvec[ishf+d];
274                 fi[i*FI_STRIDE+d] = 0;
275             }
276
277             qi[i] = facel*q[ci*UNROLLI+i];
278         }
279
280 #ifdef CALC_ENERGIES
281         if (do_self)
282         {
283             real Vc_sub_self;
284
285 #ifdef CALC_COUL_RF
286             Vc_sub_self = 0.5*c_rf;
287 #endif
288 #ifdef CALC_COUL_TAB
289 #if GMX_DOUBLE
290             Vc_sub_self = 0.5*tab_coul_V[0];
291 #else
292             Vc_sub_self = 0.5*tab_coul_FDV0[2];
293 #endif
294 #endif
295
296             if (l_cj[ciEntry.cj_ind_start].cj == ci_sh)
297             {
298                 for (i = 0; i < UNROLLI; i++)
299                 {
300                     int egp_ind;
301 #ifdef ENERGY_GROUPS
302                     egp_ind = egp_sh_i[i] + ((nbatParams.energrp[ci] >> (i*nbatParams.neg_2log)) & egp_mask);
303 #else
304                     egp_ind = 0;
305 #endif
306                     /* Coulomb self interaction */
307                     Vc[egp_ind]   -= qi[i]*q[ci*UNROLLI+i]*Vc_sub_self;
308
309 #ifdef LJ_EWALD
310                     /* LJ Ewald self interaction */
311                     Vvdw[egp_ind] += 0.5*nbatParams.nbfp[nbatParams.type[ci*UNROLLI+i]*(nbatParams.numTypes + 1)*2]/6*lje_coeff6_6;
312 #endif
313                 }
314             }
315         }
316 #endif  /* CALC_ENERGIES */
317
318         cjind = cjind0;
319         while (cjind < cjind1 && nbl->cj[cjind].excl != 0xffff)
320         {
321 #define CHECK_EXCLS
322             if (half_LJ)
323             {
324 #define CALC_COULOMB
325 #define HALF_LJ
326 #include "gromacs/nbnxm/kernels_reference/kernel_ref_inner.h"
327 #undef HALF_LJ
328 #undef CALC_COULOMB
329             }
330             else if (do_coul)
331             {
332 #define CALC_COULOMB
333 #include "gromacs/nbnxm/kernels_reference/kernel_ref_inner.h"
334 #undef CALC_COULOMB
335             }
336             else
337             {
338 #include "gromacs/nbnxm/kernels_reference/kernel_ref_inner.h"
339             }
340 #undef CHECK_EXCLS
341             cjind++;
342         }
343
344         for (; (cjind < cjind1); cjind++)
345         {
346             if (half_LJ)
347             {
348 #define CALC_COULOMB
349 #define HALF_LJ
350 #include "gromacs/nbnxm/kernels_reference/kernel_ref_inner.h"
351 #undef HALF_LJ
352 #undef CALC_COULOMB
353             }
354             else if (do_coul)
355             {
356 #define CALC_COULOMB
357 #include "gromacs/nbnxm/kernels_reference/kernel_ref_inner.h"
358 #undef CALC_COULOMB
359             }
360             else
361             {
362 #include "gromacs/nbnxm/kernels_reference/kernel_ref_inner.h"
363             }
364         }
365
366         /* Add accumulated i-forces to the force array */
367         for (i = 0; i < UNROLLI; i++)
368         {
369             for (d = 0; d < DIM; d++)
370             {
371                 f[(ci*UNROLLI+i)*F_STRIDE+d] += fi[i*FI_STRIDE+d];
372             }
373         }
374 #ifdef CALC_SHIFTFORCES
375         if (fshift != nullptr)
376         {
377             /* Add i forces to shifted force list */
378             for (i = 0; i < UNROLLI; i++)
379             {
380                 for (d = 0; d < DIM; d++)
381                 {
382                     fshift[ishf+d] += fi[i*FI_STRIDE+d];
383                 }
384             }
385         }
386 #endif
387
388 #ifdef CALC_ENERGIES
389 #ifndef ENERGY_GROUPS
390         *Vvdw += Vvdw_ci;
391         *Vc   += Vc_ci;
392 #endif
393 #endif
394     }
395
396 #ifdef COUNT_PAIRS
397     printf("atom pairs %d\n", npair);
398 #endif
399 }
400
401 #undef CALC_SHIFTFORCES
402
403 #undef X_STRIDE
404 #undef F_STRIDE
405 #undef XI_STRIDE
406 #undef FI_STRIDE
407
408 #undef UNROLLI
409 #undef UNROLLJ