Update copyright statements and change license to LGPL
[alexxy/gromacs.git] / src / mdlib / nbnxn_kernels / nbnxn_kernel_ref_outer.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2009, The GROMACS Development Team
6  * Copyright (c) 2012, by the GROMACS development team, led by
7  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
8  * others, as listed in the AUTHORS file in the top-level source
9  * directory and at http://www.gromacs.org.
10  *
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.
15  *
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.
20  *
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.
25  *
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.
33  *
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.
36  */
37
38 #define UNROLLI    NBNXN_CPU_CLUSTER_I_SIZE
39 #define UNROLLJ    NBNXN_CPU_CLUSTER_I_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_NAME(x,y) x##_rf_##y
59 #endif
60 #ifdef CALC_COUL_TAB
61 #ifndef VDW_CUTOFF_CHECK
62 #define NBK_FUNC_NAME(x,y) x##_tab_##y
63 #else
64 #define NBK_FUNC_NAME(x,y) x##_tab_twin_##y
65 #endif
66 #endif
67
68 static void
69 #ifndef CALC_ENERGIES
70 NBK_FUNC_NAME(nbnxn_kernel_ref,noener)
71 #else
72 #ifndef ENERGY_GROUPS
73 NBK_FUNC_NAME(nbnxn_kernel_ref,ener)
74 #else
75 NBK_FUNC_NAME(nbnxn_kernel_ref,energrp)
76 #endif
77 #endif
78 #undef NBK_FUNC_NAME
79                             (const nbnxn_pairlist_t     *nbl,
80                              const nbnxn_atomdata_t     *nbat,
81                              const interaction_const_t  *ic,
82                              rvec                       *shift_vec,
83                              real                       *f
84 #ifdef CALC_SHIFTFORCES
85                              ,
86                              real                       *fshift
87 #endif
88 #ifdef CALC_ENERGIES
89                              ,
90                              real                       *Vvdw,
91                              real                       *Vc
92 #endif
93                             )
94 {
95     const nbnxn_ci_t   *nbln;
96     const nbnxn_cj_t   *l_cj;
97     const int          *type;
98     const real         *q;
99     const real         *shiftvec;
100     const real         *x;
101     const real         *nbfp;
102     real       rcut2;
103 #ifdef VDW_CUTOFF_CHECK
104     real       rvdw2;
105 #endif
106     int        ntype2;
107     real       facel;
108     real       *nbfp_i;
109     int        n,ci,ci_sh;
110     int        ish,ishf;
111     gmx_bool   half_LJ,do_coul;
112     int        cjind0,cjind1,cjind;
113     int        ip,jp;
114
115     real       xi[UNROLLI*XI_STRIDE];
116     real       fi[UNROLLI*FI_STRIDE];
117     real       qi[UNROLLI];
118
119 #ifdef CALC_ENERGIES
120 #ifndef ENERGY_GROUPS
121
122     real       Vvdw_ci,Vc_ci;
123 #else
124     int        egp_mask;
125     int        egp_sh_i[UNROLLI];
126 #endif
127     real       sh_invrc6;
128 #endif
129
130 #ifdef CALC_COUL_RF
131     real       k_rf2;
132 #ifdef CALC_ENERGIES
133     real       k_rf,c_rf;
134 #endif
135 #endif
136 #ifdef CALC_COUL_TAB
137     real       tabscale;
138 #ifdef CALC_ENERGIES
139     real       halfsp;
140 #endif
141 #ifndef GMX_DOUBLE
142     const real *tab_coul_FDV0;
143 #else
144     const real *tab_coul_F;
145     const real *tab_coul_V;
146 #endif
147 #endif
148
149     int ninner;
150
151 #ifdef COUNT_PAIRS
152     int npair=0;
153 #endif
154
155 #ifdef CALC_ENERGIES
156     sh_invrc6 = ic->sh_invrc6;
157 #endif
158
159 #ifdef CALC_COUL_RF
160     k_rf2 = 2*ic->k_rf;
161 #ifdef CALC_ENERGIES
162     k_rf = ic->k_rf;
163     c_rf = ic->c_rf;
164 #endif
165 #endif
166 #ifdef CALC_COUL_TAB
167     tabscale = ic->tabq_scale;
168 #ifdef CALC_ENERGIES
169     halfsp = 0.5/ic->tabq_scale;
170 #endif
171
172 #ifndef GMX_DOUBLE
173     tab_coul_FDV0 = ic->tabq_coul_FDV0;
174 #else
175     tab_coul_F    = ic->tabq_coul_F;
176     tab_coul_V    = ic->tabq_coul_V;
177 #endif
178 #endif
179
180 #ifdef ENERGY_GROUPS
181     egp_mask = (1<<nbat->neg_2log) - 1;
182 #endif
183
184
185     rcut2               = ic->rcoulomb*ic->rcoulomb;
186 #ifdef VDW_CUTOFF_CHECK
187     rvdw2               = ic->rvdw*ic->rvdw;
188 #endif
189
190     ntype2              = nbat->ntype*2;
191     nbfp                = nbat->nbfp;
192     q                   = nbat->q;
193     type                = nbat->type;
194     facel               = ic->epsfac;
195     shiftvec            = shift_vec[0];
196     x                   = nbat->x;
197
198     l_cj = nbl->cj;
199
200     ninner = 0;
201     for(n=0; n<nbl->nci; n++)
202     {
203         int i,d;
204
205         nbln = &nbl->ci[n];
206
207         ish              = (nbln->shift & NBNXN_CI_SHIFT);
208         /* x, f and fshift are assumed to be stored with stride 3 */
209         ishf             = ish*DIM;
210         cjind0           = nbln->cj_ind_start;
211         cjind1           = nbln->cj_ind_end;
212         /* Currently only works super-cells equal to sub-cells */
213         ci               = nbln->ci;
214         ci_sh            = (ish == CENTRAL ? ci : -1);
215
216         half_LJ = (nbln->shift & NBNXN_CI_HALF_LJ(0));
217         do_coul = (nbln->shift & NBNXN_CI_DO_COUL(0));
218
219 #ifdef CALC_ENERGIES
220 #ifndef ENERGY_GROUPS
221         Vvdw_ci = 0;
222         Vc_ci   = 0;
223 #else
224         for(i=0; i<UNROLLI; i++)
225         {
226             egp_sh_i[i] = ((nbat->energrp[ci]>>(i*nbat->neg_2log)) & egp_mask)*nbat->nenergrp;
227         }
228 #endif
229 #endif
230
231         for(i=0; i<UNROLLI; i++)
232         {
233             for(d=0; d<DIM; d++)
234             {
235                 xi[i*XI_STRIDE+d] = x[(ci*UNROLLI+i)*X_STRIDE+d] + shiftvec[ishf+d];
236                 fi[i*FI_STRIDE+d] = 0;
237             }
238         }
239
240         /* With half_LJ we currently always calculate Coulomb interactions */
241         if (do_coul || half_LJ)
242         {
243 #ifdef CALC_ENERGIES
244             real Vc_sub_self;
245
246 #ifdef CALC_COUL_RF
247             Vc_sub_self = 0.5*c_rf;
248 #endif
249 #ifdef CALC_COUL_TAB
250 #ifdef GMX_DOUBLE
251             Vc_sub_self = 0.5*tab_coul_V[0];
252 #else
253             Vc_sub_self = 0.5*tab_coul_FDV0[2];
254 #endif
255 #endif
256 #endif
257
258             for(i=0; i<UNROLLI; i++)
259             {
260                 qi[i] = facel*q[ci*UNROLLI+i];
261
262 #ifdef CALC_ENERGIES
263                 if (l_cj[nbln->cj_ind_start].cj == ci_sh)
264                 {
265 #ifdef ENERGY_GROUPS
266                     Vc[egp_sh_i[i]+((nbat->energrp[ci]>>(i*nbat->neg_2log)) & egp_mask)]
267 #else
268                     Vc[0]
269 #endif
270                         -= qi[i]*q[ci*UNROLLI+i]*Vc_sub_self;
271                 }
272 #endif
273             }
274         }
275
276         cjind = cjind0;
277         while (cjind < cjind1 && nbl->cj[cjind].excl != 0xffff)
278         {
279 #define CHECK_EXCLS
280             if (half_LJ)
281             {
282 #define CALC_COULOMB
283 #define HALF_LJ
284 #include "nbnxn_kernel_ref_inner.h"
285 #undef HALF_LJ
286 #undef CALC_COULOMB
287             }
288             /* cppcheck-suppress duplicateBranch */
289             else if (do_coul)
290             {
291 #define CALC_COULOMB
292 #include "nbnxn_kernel_ref_inner.h"
293 #undef CALC_COULOMB
294             }
295             else
296             {
297 #include "nbnxn_kernel_ref_inner.h"
298             }
299 #undef CHECK_EXCLS
300             cjind++;
301         }
302
303         for(; (cjind<cjind1); cjind++)
304         {
305             if (half_LJ)
306             {
307 #define CALC_COULOMB
308 #define HALF_LJ
309 #include "nbnxn_kernel_ref_inner.h"
310 #undef HALF_LJ
311 #undef CALC_COULOMB
312             }
313             /* cppcheck-suppress duplicateBranch */
314             else if (do_coul)
315             {
316 #define CALC_COULOMB
317 #include "nbnxn_kernel_ref_inner.h"
318 #undef CALC_COULOMB
319             }
320             else
321             {
322 #include "nbnxn_kernel_ref_inner.h"
323             }
324         }
325         ninner += cjind1 - cjind0;
326
327         /* Add accumulated i-forces to the force array */
328         for(i=0; i<UNROLLI; i++)
329         {
330             for(d=0; d<DIM; d++)
331             {
332                 f[(ci*UNROLLI+i)*F_STRIDE+d] += fi[i*FI_STRIDE+d];
333             }
334         }
335 #ifdef CALC_SHIFTFORCES
336         if (fshift != NULL)
337         {
338             /* Add i forces to shifted force list */
339             for(i=0; i<UNROLLI; i++)
340             {
341                 for(d=0; d<DIM; d++)
342                 {
343                     fshift[ishf+d] += fi[i*FI_STRIDE+d];
344                 }
345             }
346         }
347 #endif
348
349 #ifdef CALC_ENERGIES
350 #ifndef ENERGY_GROUPS
351         *Vvdw += Vvdw_ci;
352         *Vc   += Vc_ci;
353 #endif
354 #endif
355         }
356
357 #ifdef COUNT_PAIRS
358     printf("atom pairs %d\n",npair);
359 #endif
360 }
361
362 #undef CALC_SHIFTFORCES
363
364 #undef X_STRIDE
365 #undef F_STRIDE
366 #undef XI_STRIDE
367 #undef FI_STRIDE
368
369 #undef UNROLLI
370 #undef UNROLLJ