38b0293872682a5b49ce30bc017b3eb3b37fad0c
[alexxy/gromacs.git] / src / gromacs / mdlib / nbnxn_kernels / simd_2xnn / nbnxn_kernel_simd_2xnn_outer.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014, 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
37 /* Half-width SIMD operations are required here.
38  * As the 4xn kernels are the "standard" kernels and some special operations
39  * are required only here, we define those in nbnxn_kernel_simd_utils_...
40  *
41  * Half-width SIMD real type:
42  * gmx_mm_hpr
43  *
44  * Half-width SIMD operations
45  * Load reals at half-width aligned pointer b into half-width SIMD register a:
46  * gmx_load_hpr(a, b)
47  * Set all entries in half-width SIMD register *a to b:
48  * gmx_set1_hpr(a, b)
49  * Load one real at b and one real at b+1 into halves of a, respectively:
50  * gmx_load1p1_pr(a, b)
51  * Load reals at half-width aligned pointer b into two halves of a:
52  * gmx_loaddh_pr(a, b)
53  * Store half-width SIMD register b into half width aligned memory a:
54  * gmx_store_hpr(a, b)
55  * gmx_add_hpr(a, b)
56  * gmx_sub_hpr(a, b)
57  * Sum over 4 half SIMD registers:
58  * gmx_sum4_hpr(a, b)
59  * Sum the elements of halfs of each input register and store sums in out:
60  * gmx_mm_transpose_sum4h_pr(a, b)
61  * Extract two half-width registers *b, *c from a full width register a:
62  * gmx_pr_to_2hpr(a, b, c)
63  */
64
65
66 {
67     const nbnxn_ci_t   *nbln;
68     const nbnxn_cj_t   *l_cj;
69     const int          *type;
70     const real         *q;
71     const real         *shiftvec;
72     const real         *x;
73     const real         *nbfp0, *nbfp1, *nbfp2 = NULL, *nbfp3 = NULL;
74     real                facel;
75     real               *nbfp_ptr;
76     int                 n, ci, ci_sh;
77     int                 ish, ish3;
78     gmx_bool            do_LJ, half_LJ, do_coul, do_self;
79     int                 sci, scix, sciy, sciz, sci2;
80     int                 cjind0, cjind1, cjind;
81     int                 ip, jp;
82
83 #ifdef ENERGY_GROUPS
84     int         Vstride_i;
85     int         egps_ishift, egps_imask;
86     int         egps_jshift, egps_jmask, egps_jstride;
87     int         egps_i;
88     real       *vvdwtp[UNROLLI];
89     real       *vctp[UNROLLI];
90 #endif
91
92     gmx_simd_real_t  shX_S;
93     gmx_simd_real_t  shY_S;
94     gmx_simd_real_t  shZ_S;
95     gmx_simd_real_t  ix_S0, iy_S0, iz_S0;
96     gmx_simd_real_t  ix_S2, iy_S2, iz_S2;
97     gmx_simd_real_t  fix_S0, fiy_S0, fiz_S0;
98     gmx_simd_real_t  fix_S2, fiy_S2, fiz_S2;
99     /* We use an i-force SIMD register width of 4 */
100     /* The pr4 stuff is defined in nbnxn_kernel_simd_utils.h */
101     gmx_simd4_real_t fix_S, fiy_S, fiz_S;
102
103     gmx_simd_real_t  diagonal_jmi_S;
104 #if UNROLLI == UNROLLJ
105     gmx_simd_bool_t  diagonal_mask_S0, diagonal_mask_S2;
106 #else
107     gmx_simd_bool_t  diagonal_mask0_S0, diagonal_mask0_S2;
108     gmx_simd_bool_t  diagonal_mask1_S0, diagonal_mask1_S2;
109 #endif
110
111     unsigned            *exclusion_filter;
112     gmx_exclfilter       filter_S0, filter_S2;
113
114     gmx_simd_real_t      zero_S = gmx_simd_set1_r(0.0);
115
116     gmx_simd_real_t      one_S = gmx_simd_set1_r(1.0);
117     gmx_simd_real_t      iq_S0 = gmx_simd_setzero_r();
118     gmx_simd_real_t      iq_S2 = gmx_simd_setzero_r();
119
120 #ifdef CALC_COUL_RF
121     gmx_simd_real_t      mrc_3_S;
122 #ifdef CALC_ENERGIES
123     gmx_simd_real_t      hrc_3_S, moh_rc_S;
124 #endif
125 #endif
126
127 #ifdef CALC_COUL_TAB
128     /* Coulomb table variables */
129     gmx_simd_real_t   invtsp_S;
130     const real       *tab_coul_F;
131 #ifndef TAB_FDV0
132     const real       *tab_coul_V;
133 #endif
134     /* Thread-local working buffers for force and potential lookups */
135     int               ti0_array[2*GMX_SIMD_REAL_WIDTH], *ti0 = NULL;
136     int               ti2_array[2*GMX_SIMD_REAL_WIDTH], *ti2 = NULL;
137 #ifdef CALC_ENERGIES
138     gmx_simd_real_t   mhalfsp_S;
139 #endif
140 #endif
141
142 #ifdef CALC_COUL_EWALD
143     gmx_simd_real_t beta2_S, beta_S;
144 #endif
145
146 #if defined CALC_ENERGIES && (defined CALC_COUL_EWALD || defined CALC_COUL_TAB)
147     gmx_simd_real_t  sh_ewald_S;
148 #endif
149
150 #if defined LJ_CUT && defined CALC_ENERGIES
151     gmx_simd_real_t   p6_cpot_S, p12_cpot_S;
152 #endif
153 #ifdef LJ_POT_SWITCH
154     gmx_simd_real_t   rswitch_S;
155     gmx_simd_real_t   swV3_S, swV4_S, swV5_S;
156     gmx_simd_real_t   swF2_S, swF3_S, swF4_S;
157 #endif
158 #ifdef LJ_FORCE_SWITCH
159     gmx_simd_real_t   rswitch_S;
160     gmx_simd_real_t   p6_fc2_S, p6_fc3_S;
161     gmx_simd_real_t   p12_fc2_S, p12_fc3_S;
162 #ifdef CALC_ENERGIES
163     gmx_simd_real_t   p6_vc3_S, p6_vc4_S;
164     gmx_simd_real_t   p12_vc3_S, p12_vc4_S;
165     gmx_simd_real_t   p6_6cpot_S, p12_12cpot_S;
166 #endif
167 #endif
168 #ifdef LJ_EWALD_GEOM
169     real              lj_ewaldcoeff2, lj_ewaldcoeff6_6;
170     gmx_simd_real_t   mone_S, half_S, lje_c2_S, lje_c6_6_S, lje_vc_S;
171 #endif
172
173 #ifdef LJ_COMB_LB
174     const real       *ljc;
175
176     gmx_simd_real_t   hsig_i_S0, seps_i_S0;
177     gmx_simd_real_t   hsig_i_S2, seps_i_S2;
178 #else
179 #ifdef FIX_LJ_C
180     real              pvdw_array[2*UNROLLI*UNROLLJ+GMX_SIMD_REAL_WIDTH];
181     real             *pvdw_c6, *pvdw_c12;
182     gmx_simd_real_t   c6_S0, c12_S0;
183     gmx_simd_real_t   c6_S2, c12_S2;
184 #endif
185
186 #if defined LJ_COMB_GEOM || defined LJ_EWALD_GEOM
187     const real       *ljc;
188
189     gmx_simd_real_t   c6s_S0, c12s_S0;
190     gmx_simd_real_t   c6s_S2  = gmx_simd_setzero_r();
191     gmx_simd_real_t   c12s_S2 = gmx_simd_setzero_r();
192 #endif
193 #endif /* LJ_COMB_LB */
194
195     gmx_simd_real_t  vctot_S, Vvdwtot_S;
196     gmx_simd_real_t  sixth_S, twelveth_S;
197
198     gmx_simd_real_t  avoid_sing_S;
199     gmx_simd_real_t  rc2_S;
200 #ifdef VDW_CUTOFF_CHECK
201     gmx_simd_real_t  rcvdw2_S;
202 #endif
203
204 #ifdef CALC_ENERGIES
205     /* cppcheck-suppress unassignedVariable */
206     real       tmpsum_array[2*GMX_SIMD_REAL_WIDTH], *tmpsum;
207 #endif
208 #ifdef CALC_SHIFTFORCES
209     /* cppcheck-suppress unassignedVariable */
210     real       shf_array[2*GMX_SIMD_REAL_WIDTH], *shf;
211 #endif
212
213     int ninner;
214
215 #ifdef COUNT_PAIRS
216     int npair = 0;
217 #endif
218
219 #if defined LJ_COMB_GEOM || defined LJ_COMB_LB || defined LJ_EWALD_GEOM
220     ljc = nbat->lj_comb;
221 #endif
222 #if !(defined LJ_COMB_GEOM || defined LJ_COMB_LB)
223     /* No combination rule used */
224     nbfp_ptr    = (4 == nbfp_stride) ? nbat->nbfp_s4 : nbat->nbfp;
225 #endif
226
227     /* Load j-i for the first i */
228     diagonal_jmi_S    = gmx_simd_load_r(nbat->simd_2xnn_diagonal_j_minus_i);
229     /* Generate all the diagonal masks as comparison results */
230 #if UNROLLI == UNROLLJ
231     diagonal_mask_S0  = gmx_simd_cmplt_r(zero_S, diagonal_jmi_S);
232     diagonal_jmi_S    = gmx_simd_sub_r(diagonal_jmi_S, one_S);
233     diagonal_jmi_S    = gmx_simd_sub_r(diagonal_jmi_S, one_S);
234     diagonal_mask_S2  = gmx_simd_cmplt_r(zero_S, diagonal_jmi_S);
235 #else
236 #if 2*UNROLLI == UNROLLJ
237     diagonal_mask0_S0 = gmx_simd_cmplt_r(zero_S, diagonal_jmi_S);
238     diagonal_jmi_S    = gmx_simd_sub_r(diagonal_jmi_S, one_S);
239     diagonal_jmi_S    = gmx_simd_sub_r(diagonal_jmi_S, one_S);
240     diagonal_mask0_S2 = gmx_simd_cmplt_r(zero_S, diagonal_jmi_S);
241     diagonal_jmi_S    = gmx_simd_sub_r(diagonal_jmi_S, one_S);
242     diagonal_jmi_S    = gmx_simd_sub_r(diagonal_jmi_S, one_S);
243     diagonal_mask1_S0 = gmx_simd_cmplt_r(zero_S, diagonal_jmi_S);
244     diagonal_jmi_S    = gmx_simd_sub_r(diagonal_jmi_S, one_S);
245     diagonal_jmi_S    = gmx_simd_sub_r(diagonal_jmi_S, one_S);
246     diagonal_mask1_S2 = gmx_simd_cmplt_r(zero_S, diagonal_jmi_S);
247 #endif
248 #endif
249
250     /* Load masks for topology exclusion masking. filter_stride is
251        static const, so the conditional will be optimized away. */
252     if (1 == filter_stride)
253     {
254         exclusion_filter = nbat->simd_exclusion_filter1;
255     }
256     else /* (2 == filter_stride) */
257     {
258         exclusion_filter = nbat->simd_exclusion_filter2;
259     }
260
261     /* Here we cast the exclusion filters from unsigned * to int * or real *.
262      * Since we only check bits, the actual value they represent does not
263      * matter, as long as both filter and mask data are treated the same way.
264      */
265     filter_S0 = gmx_load_exclusion_filter(exclusion_filter + 0*2*UNROLLJ*filter_stride);
266     filter_S2 = gmx_load_exclusion_filter(exclusion_filter + 1*2*UNROLLJ*filter_stride);
267
268 #ifdef CALC_COUL_RF
269     /* Reaction-field constants */
270     mrc_3_S  = gmx_simd_set1_r(-2*ic->k_rf);
271 #ifdef CALC_ENERGIES
272     hrc_3_S  = gmx_simd_set1_r(ic->k_rf);
273     moh_rc_S = gmx_simd_set1_r(-ic->c_rf);
274 #endif
275 #endif
276
277 #ifdef CALC_COUL_TAB
278     /* Generate aligned table index pointers */
279     ti0 = prepare_table_load_buffer(ti0_array);
280     ti2 = prepare_table_load_buffer(ti2_array);
281
282     invtsp_S  = gmx_simd_set1_r(ic->tabq_scale);
283 #ifdef CALC_ENERGIES
284     mhalfsp_S = gmx_simd_set1_r(-0.5/ic->tabq_scale);
285 #endif
286
287 #ifdef TAB_FDV0
288     tab_coul_F = ic->tabq_coul_FDV0;
289 #else
290     tab_coul_F = ic->tabq_coul_F;
291     tab_coul_V = ic->tabq_coul_V;
292 #endif
293 #endif /* CALC_COUL_TAB */
294
295 #ifdef CALC_COUL_EWALD
296     beta2_S = gmx_simd_set1_r(ic->ewaldcoeff_q*ic->ewaldcoeff_q);
297     beta_S  = gmx_simd_set1_r(ic->ewaldcoeff_q);
298 #endif
299
300 #if (defined CALC_COUL_TAB || defined CALC_COUL_EWALD) && defined CALC_ENERGIES
301     sh_ewald_S = gmx_simd_set1_r(ic->sh_ewald);
302 #endif
303
304     /* LJ function constants */
305 #if defined CALC_ENERGIES || defined LJ_POT_SWITCH
306     sixth_S      = gmx_simd_set1_r(1.0/6.0);
307     twelveth_S   = gmx_simd_set1_r(1.0/12.0);
308 #endif
309
310 #if defined LJ_CUT && defined CALC_ENERGIES
311     /* We shift the potential by cpot, which can be zero */
312     p6_cpot_S    = gmx_simd_set1_r(ic->dispersion_shift.cpot);
313     p12_cpot_S   = gmx_simd_set1_r(ic->repulsion_shift.cpot);
314 #endif
315 #ifdef LJ_POT_SWITCH
316     rswitch_S = gmx_simd_set1_r(ic->rvdw_switch);
317     swV3_S    = gmx_simd_set1_r(ic->vdw_switch.c3);
318     swV4_S    = gmx_simd_set1_r(ic->vdw_switch.c4);
319     swV5_S    = gmx_simd_set1_r(ic->vdw_switch.c5);
320     swF2_S    = gmx_simd_set1_r(3*ic->vdw_switch.c3);
321     swF3_S    = gmx_simd_set1_r(4*ic->vdw_switch.c4);
322     swF4_S    = gmx_simd_set1_r(5*ic->vdw_switch.c5);
323 #endif
324 #ifdef LJ_FORCE_SWITCH
325     rswitch_S = gmx_simd_set1_r(ic->rvdw_switch);
326     p6_fc2_S  = gmx_simd_set1_r(ic->dispersion_shift.c2);
327     p6_fc3_S  = gmx_simd_set1_r(ic->dispersion_shift.c3);
328     p12_fc2_S = gmx_simd_set1_r(ic->repulsion_shift.c2);
329     p12_fc3_S = gmx_simd_set1_r(ic->repulsion_shift.c3);
330 #ifdef CALC_ENERGIES
331     {
332         gmx_simd_real_t mthird_S  = gmx_simd_set1_r(-1.0/3.0);
333         gmx_simd_real_t mfourth_S = gmx_simd_set1_r(-1.0/4.0);
334
335         p6_vc3_S     = gmx_simd_mul_r(mthird_S,  p6_fc2_S);
336         p6_vc4_S     = gmx_simd_mul_r(mfourth_S, p6_fc3_S);
337         p6_6cpot_S   = gmx_simd_set1_r(ic->dispersion_shift.cpot/6);
338         p12_vc3_S    = gmx_simd_mul_r(mthird_S,  p12_fc2_S);
339         p12_vc4_S    = gmx_simd_mul_r(mfourth_S, p12_fc3_S);
340         p12_12cpot_S = gmx_simd_set1_r(ic->repulsion_shift.cpot/12);
341     }
342 #endif
343 #endif
344 #ifdef LJ_EWALD_GEOM
345     mone_S           = gmx_simd_set1_r(-1.0);
346     half_S           = gmx_simd_set1_r(0.5);
347     lj_ewaldcoeff2   = ic->ewaldcoeff_lj*ic->ewaldcoeff_lj;
348     lj_ewaldcoeff6_6 = lj_ewaldcoeff2*lj_ewaldcoeff2*lj_ewaldcoeff2/6;
349     lje_c2_S         = gmx_simd_set1_r(lj_ewaldcoeff2);
350     lje_c6_6_S       = gmx_simd_set1_r(lj_ewaldcoeff6_6);
351     /* Determine the grid potential at the cut-off */
352     lje_vc_S         = gmx_simd_set1_r(ic->sh_lj_ewald);
353 #endif
354
355     /* The kernel either supports rcoulomb = rvdw or rcoulomb >= rvdw */
356     rc2_S    = gmx_simd_set1_r(ic->rcoulomb*ic->rcoulomb);
357 #ifdef VDW_CUTOFF_CHECK
358     rcvdw2_S = gmx_simd_set1_r(ic->rvdw*ic->rvdw);
359 #endif
360
361     avoid_sing_S = gmx_simd_set1_r(NBNXN_AVOID_SING_R2_INC);
362
363     q                   = nbat->q;
364     type                = nbat->type;
365     facel               = ic->epsfac;
366     shiftvec            = shift_vec[0];
367     x                   = nbat->x;
368
369 #ifdef CALC_ENERGIES
370     tmpsum   = gmx_simd_align_r(tmpsum_array);
371 #endif
372 #ifdef CALC_SHIFTFORCES
373     shf      = gmx_simd_align_r(shf_array);
374 #endif
375
376 #ifdef FIX_LJ_C
377     pvdw_c6  = gmx_simd_align_r(pvdw_array);
378     pvdw_c12 = pvdw_c6 + UNROLLI*UNROLLJ;
379
380     for (jp = 0; jp < UNROLLJ; jp++)
381     {
382         pvdw_c6 [0*UNROLLJ+jp] = nbat->nbfp[0*2];
383         pvdw_c6 [1*UNROLLJ+jp] = nbat->nbfp[0*2];
384         pvdw_c6 [2*UNROLLJ+jp] = nbat->nbfp[0*2];
385         pvdw_c6 [3*UNROLLJ+jp] = nbat->nbfp[0*2];
386
387         pvdw_c12[0*UNROLLJ+jp] = nbat->nbfp[0*2+1];
388         pvdw_c12[1*UNROLLJ+jp] = nbat->nbfp[0*2+1];
389         pvdw_c12[2*UNROLLJ+jp] = nbat->nbfp[0*2+1];
390         pvdw_c12[3*UNROLLJ+jp] = nbat->nbfp[0*2+1];
391     }
392     c6_S0            = gmx_simd_load_r(pvdw_c6 +0*UNROLLJ);
393     c6_S1            = gmx_simd_load_r(pvdw_c6 +1*UNROLLJ);
394     c6_S2            = gmx_simd_load_r(pvdw_c6 +2*UNROLLJ);
395     c6_S3            = gmx_simd_load_r(pvdw_c6 +3*UNROLLJ);
396
397     c12_S0           = gmx_simd_load_r(pvdw_c12+0*UNROLLJ);
398     c12_S1           = gmx_simd_load_r(pvdw_c12+1*UNROLLJ);
399     c12_S2           = gmx_simd_load_r(pvdw_c12+2*UNROLLJ);
400     c12_S3           = gmx_simd_load_r(pvdw_c12+3*UNROLLJ);
401 #endif /* FIX_LJ_C */
402
403 #ifdef ENERGY_GROUPS
404     egps_ishift  = nbat->neg_2log;
405     egps_imask   = (1<<egps_ishift) - 1;
406     egps_jshift  = 2*nbat->neg_2log;
407     egps_jmask   = (1<<egps_jshift) - 1;
408     egps_jstride = (UNROLLJ>>1)*UNROLLJ;
409     /* Major division is over i-particle energy groups, determine the stride */
410     Vstride_i    = nbat->nenergrp*(1<<nbat->neg_2log)*egps_jstride;
411 #endif
412
413     l_cj = nbl->cj;
414
415     ninner = 0;
416     for (n = 0; n < nbl->nci; n++)
417     {
418         nbln = &nbl->ci[n];
419
420         ish              = (nbln->shift & NBNXN_CI_SHIFT);
421         ish3             = ish*3;
422         cjind0           = nbln->cj_ind_start;
423         cjind1           = nbln->cj_ind_end;
424         ci               = nbln->ci;
425         ci_sh            = (ish == CENTRAL ? ci : -1);
426
427         shX_S = gmx_simd_load1_r(shiftvec+ish3);
428         shY_S = gmx_simd_load1_r(shiftvec+ish3+1);
429         shZ_S = gmx_simd_load1_r(shiftvec+ish3+2);
430
431 #if UNROLLJ <= 4
432         sci              = ci*STRIDE;
433         scix             = sci*DIM;
434         sci2             = sci*2;
435 #else
436         sci              = (ci>>1)*STRIDE;
437         scix             = sci*DIM + (ci & 1)*(STRIDE>>1);
438         sci2             = sci*2 + (ci & 1)*(STRIDE>>1);
439         sci             += (ci & 1)*(STRIDE>>1);
440 #endif
441
442         /* We have 5 LJ/C combinations, but use only three inner loops,
443          * as the other combinations are unlikely and/or not much faster:
444          * inner half-LJ + C for half-LJ + C / no-LJ + C
445          * inner LJ + C      for full-LJ + C
446          * inner LJ          for full-LJ + no-C / half-LJ + no-C
447          */
448         do_LJ   = (nbln->shift & NBNXN_CI_DO_LJ(0));
449         do_coul = (nbln->shift & NBNXN_CI_DO_COUL(0));
450         half_LJ = ((nbln->shift & NBNXN_CI_HALF_LJ(0)) || !do_LJ) && do_coul;
451 #ifdef LJ_EWALD_GEOM
452         do_self = TRUE;
453 #else
454         do_self = do_coul;
455 #endif
456
457 #ifdef ENERGY_GROUPS
458         egps_i = nbat->energrp[ci];
459         {
460             int ia, egp_ia;
461
462             for (ia = 0; ia < UNROLLI; ia++)
463             {
464                 egp_ia     = (egps_i >> (ia*egps_ishift)) & egps_imask;
465                 vvdwtp[ia] = Vvdw + egp_ia*Vstride_i;
466                 vctp[ia]   = Vc   + egp_ia*Vstride_i;
467             }
468         }
469 #endif
470
471 #ifdef CALC_ENERGIES
472 #if UNROLLJ == 4
473         if (do_self && l_cj[nbln->cj_ind_start].cj == ci_sh)
474 #endif
475 #if UNROLLJ == 8
476         if (do_self && l_cj[nbln->cj_ind_start].cj == (ci_sh>>1))
477 #endif
478         {
479             if (do_coul)
480             {
481                 real Vc_sub_self;
482                 int  ia;
483
484 #ifdef CALC_COUL_RF
485                 Vc_sub_self = 0.5*ic->c_rf;
486 #endif
487 #ifdef CALC_COUL_TAB
488 #ifdef TAB_FDV0
489                 Vc_sub_self = 0.5*tab_coul_F[2];
490 #else
491                 Vc_sub_self = 0.5*tab_coul_V[0];
492 #endif
493 #endif
494 #ifdef CALC_COUL_EWALD
495                 /* beta/sqrt(pi) */
496                 Vc_sub_self = 0.5*ic->ewaldcoeff_q*M_2_SQRTPI;
497 #endif
498
499                 for (ia = 0; ia < UNROLLI; ia++)
500                 {
501                     real qi;
502
503                     qi = q[sci+ia];
504 #ifdef ENERGY_GROUPS
505                     vctp[ia][((egps_i>>(ia*egps_ishift)) & egps_imask)*egps_jstride]
506 #else
507                     Vc[0]
508 #endif
509                         -= facel*qi*qi*Vc_sub_self;
510                 }
511             }
512
513 #ifdef LJ_EWALD_GEOM
514             {
515                 int  ia;
516
517                 for (ia = 0; ia < UNROLLI; ia++)
518                 {
519                     real c6_i;
520
521                     c6_i = nbat->nbfp[nbat->type[sci+ia]*(nbat->ntype + 1)*2]/6;
522 #ifdef ENERGY_GROUPS
523                     vvdwtp[ia][((egps_i>>(ia*egps_ishift)) & egps_imask)*egps_jstride]
524 #else
525                     Vvdw[0]
526 #endif
527                         += 0.5*c6_i*lj_ewaldcoeff6_6;
528                 }
529             }
530 #endif      /* LJ_EWALD */
531         }
532 #endif
533
534         /* Load i atom data */
535         sciy             = scix + STRIDE;
536         sciz             = sciy + STRIDE;
537         gmx_load1p1_pr(&ix_S0, x+scix);
538         gmx_load1p1_pr(&ix_S2, x+scix+2);
539         gmx_load1p1_pr(&iy_S0, x+sciy);
540         gmx_load1p1_pr(&iy_S2, x+sciy+2);
541         gmx_load1p1_pr(&iz_S0, x+sciz);
542         gmx_load1p1_pr(&iz_S2, x+sciz+2);
543         ix_S0          = gmx_simd_add_r(ix_S0, shX_S);
544         ix_S2          = gmx_simd_add_r(ix_S2, shX_S);
545         iy_S0          = gmx_simd_add_r(iy_S0, shY_S);
546         iy_S2          = gmx_simd_add_r(iy_S2, shY_S);
547         iz_S0          = gmx_simd_add_r(iz_S0, shZ_S);
548         iz_S2          = gmx_simd_add_r(iz_S2, shZ_S);
549
550         if (do_coul)
551         {
552             gmx_simd_real_t facel_S;
553
554             facel_S    = gmx_simd_set1_r(facel);
555
556             gmx_load1p1_pr(&iq_S0, q+sci);
557             gmx_load1p1_pr(&iq_S2, q+sci+2);
558             iq_S0      = gmx_simd_mul_r(facel_S, iq_S0);
559             iq_S2      = gmx_simd_mul_r(facel_S, iq_S2);
560         }
561
562 #ifdef LJ_COMB_LB
563         gmx_load1p1_pr(&hsig_i_S0, ljc+sci2+0);
564         gmx_load1p1_pr(&hsig_i_S2, ljc+sci2+2);
565         gmx_load1p1_pr(&seps_i_S0, ljc+sci2+STRIDE+0);
566         gmx_load1p1_pr(&seps_i_S2, ljc+sci2+STRIDE+2);
567 #else
568 #ifdef LJ_COMB_GEOM
569         gmx_load1p1_pr(&c6s_S0, ljc+sci2+0);
570         if (!half_LJ)
571         {
572             gmx_load1p1_pr(&c6s_S2, ljc+sci2+2);
573         }
574         gmx_load1p1_pr(&c12s_S0, ljc+sci2+STRIDE+0);
575         if (!half_LJ)
576         {
577             gmx_load1p1_pr(&c12s_S2, ljc+sci2+STRIDE+2);
578         }
579 #else
580         nbfp0     = nbfp_ptr + type[sci  ]*nbat->ntype*nbfp_stride;
581         nbfp1     = nbfp_ptr + type[sci+1]*nbat->ntype*nbfp_stride;
582         if (!half_LJ)
583         {
584             nbfp2 = nbfp_ptr + type[sci+2]*nbat->ntype*nbfp_stride;
585             nbfp3 = nbfp_ptr + type[sci+3]*nbat->ntype*nbfp_stride;
586         }
587 #endif
588 #endif
589 #ifdef LJ_EWALD_GEOM
590         /* We need the geometrically combined C6 for the PME grid correction */
591         gmx_load1p1_pr(&c6s_S0, ljc+sci2+0);
592         if (!half_LJ)
593         {
594             gmx_load1p1_pr(&c6s_S2, ljc+sci2+2);
595         }
596 #endif
597
598         /* Zero the potential energy for this list */
599         Vvdwtot_S        = gmx_simd_setzero_r();
600         vctot_S          = gmx_simd_setzero_r();
601
602         /* Clear i atom forces */
603         fix_S0           = gmx_simd_setzero_r();
604         fix_S2           = gmx_simd_setzero_r();
605         fiy_S0           = gmx_simd_setzero_r();
606         fiy_S2           = gmx_simd_setzero_r();
607         fiz_S0           = gmx_simd_setzero_r();
608         fiz_S2           = gmx_simd_setzero_r();
609
610         cjind = cjind0;
611
612         /* Currently all kernels use (at least half) LJ */
613 #define CALC_LJ
614         if (half_LJ)
615         {
616             /* Coulomb: all i-atoms, LJ: first half i-atoms */
617 #define CALC_COULOMB
618 #define HALF_LJ
619 #define CHECK_EXCLS
620             while (cjind < cjind1 && nbl->cj[cjind].excl != NBNXN_INTERACTION_MASK_ALL)
621             {
622 #include "nbnxn_kernel_simd_2xnn_inner.h"
623                 cjind++;
624             }
625 #undef CHECK_EXCLS
626             for (; (cjind < cjind1); cjind++)
627             {
628 #include "nbnxn_kernel_simd_2xnn_inner.h"
629             }
630 #undef HALF_LJ
631 #undef CALC_COULOMB
632         }
633         else if (do_coul)
634         {
635             /* Coulomb: all i-atoms, LJ: all i-atoms */
636 #define CALC_COULOMB
637 #define CHECK_EXCLS
638             while (cjind < cjind1 && nbl->cj[cjind].excl != NBNXN_INTERACTION_MASK_ALL)
639             {
640 #include "nbnxn_kernel_simd_2xnn_inner.h"
641                 cjind++;
642             }
643 #undef CHECK_EXCLS
644             for (; (cjind < cjind1); cjind++)
645             {
646 #include "nbnxn_kernel_simd_2xnn_inner.h"
647             }
648 #undef CALC_COULOMB
649         }
650         else
651         {
652             /* Coulomb: none, LJ: all i-atoms */
653 #define CHECK_EXCLS
654             while (cjind < cjind1 && nbl->cj[cjind].excl != NBNXN_INTERACTION_MASK_ALL)
655             {
656 #include "nbnxn_kernel_simd_2xnn_inner.h"
657                 cjind++;
658             }
659 #undef CHECK_EXCLS
660             for (; (cjind < cjind1); cjind++)
661             {
662 #include "nbnxn_kernel_simd_2xnn_inner.h"
663             }
664         }
665 #undef CALC_LJ
666         ninner += cjind1 - cjind0;
667
668         /* Add accumulated i-forces to the force array */
669         fix_S = gmx_mm_transpose_sum4h_pr(fix_S0, fix_S2);
670         gmx_simd4_store_r(f+scix, gmx_add_pr4(fix_S, gmx_simd4_load_r(f+scix)));
671
672         fiy_S = gmx_mm_transpose_sum4h_pr(fiy_S0, fiy_S2);
673         gmx_simd4_store_r(f+sciy, gmx_add_pr4(fiy_S, gmx_simd4_load_r(f+sciy)));
674
675         fiz_S = gmx_mm_transpose_sum4h_pr(fiz_S0, fiz_S2);
676         gmx_simd4_store_r(f+sciz, gmx_add_pr4(fiz_S, gmx_simd4_load_r(f+sciz)));
677
678 #ifdef CALC_SHIFTFORCES
679         fshift[ish3+0] += gmx_sum_simd4(fix_S, shf);
680         fshift[ish3+1] += gmx_sum_simd4(fiy_S, shf);
681         fshift[ish3+2] += gmx_sum_simd4(fiz_S, shf);
682 #endif
683
684 #ifdef CALC_ENERGIES
685         if (do_coul)
686         {
687             *Vc += gmx_sum_simd(vctot_S, tmpsum);
688         }
689
690         *Vvdw += gmx_sum_simd(Vvdwtot_S, tmpsum);
691 #endif
692
693         /* Outer loop uses 6 flops/iteration */
694     }
695
696 #ifdef COUNT_PAIRS
697     printf("atom pairs %d\n", npair);
698 #endif
699 }