Remove all unnecessary HAVE_CONFIG_H
[alexxy/gromacs.git] / src / gromacs / gmxlib / nonbonded / nb_kernel_avx_256_single / nb_kernel_ElecEw_VdwCSTab_GeomW4P1_avx_256_single.c
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  * Note: this file was generated by the GROMACS avx_256_single kernel generator.
37  */
38 #include "config.h"
39
40 #include <math.h>
41
42 #include "../nb_kernel.h"
43 #include "types/simple.h"
44 #include "gromacs/math/vec.h"
45 #include "nrnb.h"
46
47 #include "gromacs/simd/math_x86_avx_256_single.h"
48 #include "kernelutil_x86_avx_256_single.h"
49
50 /*
51  * Gromacs nonbonded kernel:   nb_kernel_ElecEw_VdwCSTab_GeomW4P1_VF_avx_256_single
52  * Electrostatics interaction: Ewald
53  * VdW interaction:            CubicSplineTable
54  * Geometry:                   Water4-Particle
55  * Calculate force/pot:        PotentialAndForce
56  */
57 void
58 nb_kernel_ElecEw_VdwCSTab_GeomW4P1_VF_avx_256_single
59                     (t_nblist                    * gmx_restrict       nlist,
60                      rvec                        * gmx_restrict          xx,
61                      rvec                        * gmx_restrict          ff,
62                      t_forcerec                  * gmx_restrict          fr,
63                      t_mdatoms                   * gmx_restrict     mdatoms,
64                      nb_kernel_data_t gmx_unused * gmx_restrict kernel_data,
65                      t_nrnb                      * gmx_restrict        nrnb)
66 {
67     /* Suffixes 0,1,2,3 refer to particle indices for waters in the inner or outer loop, or 
68      * just 0 for non-waters.
69      * Suffixes A,B,C,D,E,F,G,H refer to j loop unrolling done with AVX, e.g. for the eight different
70      * jnr indices corresponding to data put in the four positions in the SIMD register.
71      */
72     int              i_shift_offset,i_coord_offset,outeriter,inneriter;
73     int              j_index_start,j_index_end,jidx,nri,inr,ggid,iidx;
74     int              jnrA,jnrB,jnrC,jnrD;
75     int              jnrE,jnrF,jnrG,jnrH;
76     int              jnrlistA,jnrlistB,jnrlistC,jnrlistD;
77     int              jnrlistE,jnrlistF,jnrlistG,jnrlistH;
78     int              j_coord_offsetA,j_coord_offsetB,j_coord_offsetC,j_coord_offsetD;
79     int              j_coord_offsetE,j_coord_offsetF,j_coord_offsetG,j_coord_offsetH;
80     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
81     real             rcutoff_scalar;
82     real             *shiftvec,*fshift,*x,*f;
83     real             *fjptrA,*fjptrB,*fjptrC,*fjptrD,*fjptrE,*fjptrF,*fjptrG,*fjptrH;
84     real             scratch[4*DIM];
85     __m256           tx,ty,tz,fscal,rcutoff,rcutoff2,jidxall;
86     real *           vdwioffsetptr0;
87     __m256           ix0,iy0,iz0,fix0,fiy0,fiz0,iq0,isai0;
88     real *           vdwioffsetptr1;
89     __m256           ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
90     real *           vdwioffsetptr2;
91     __m256           ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
92     real *           vdwioffsetptr3;
93     __m256           ix3,iy3,iz3,fix3,fiy3,fiz3,iq3,isai3;
94     int              vdwjidx0A,vdwjidx0B,vdwjidx0C,vdwjidx0D,vdwjidx0E,vdwjidx0F,vdwjidx0G,vdwjidx0H;
95     __m256           jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
96     __m256           dx00,dy00,dz00,rsq00,rinv00,rinvsq00,r00,qq00,c6_00,c12_00;
97     __m256           dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10;
98     __m256           dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20;
99     __m256           dx30,dy30,dz30,rsq30,rinv30,rinvsq30,r30,qq30,c6_30,c12_30;
100     __m256           velec,felec,velecsum,facel,crf,krf,krf2;
101     real             *charge;
102     int              nvdwtype;
103     __m256           rinvsix,rvdw,vvdw,vvdw6,vvdw12,fvdw,fvdw6,fvdw12,vvdwsum,sh_vdw_invrcut6;
104     int              *vdwtype;
105     real             *vdwparam;
106     __m256           one_sixth   = _mm256_set1_ps(1.0/6.0);
107     __m256           one_twelfth = _mm256_set1_ps(1.0/12.0);
108     __m256i          vfitab;
109     __m128i          vfitab_lo,vfitab_hi;
110     __m128i          ifour       = _mm_set1_epi32(4);
111     __m256           rt,vfeps,vftabscale,Y,F,G,H,Heps,Fp,VV,FF;
112     real             *vftab;
113     __m256i          ewitab;
114     __m128i          ewitab_lo,ewitab_hi;
115     __m256           ewtabscale,eweps,sh_ewald,ewrt,ewtabhalfspace,ewtabF,ewtabFn,ewtabD,ewtabV;
116     __m256           beta,beta2,beta3,zeta2,pmecorrF,pmecorrV,rinv3;
117     real             *ewtab;
118     __m256           dummy_mask,cutoff_mask;
119     __m256           signbit = _mm256_castsi256_ps( _mm256_set1_epi32(0x80000000) );
120     __m256           one     = _mm256_set1_ps(1.0);
121     __m256           two     = _mm256_set1_ps(2.0);
122     x                = xx[0];
123     f                = ff[0];
124
125     nri              = nlist->nri;
126     iinr             = nlist->iinr;
127     jindex           = nlist->jindex;
128     jjnr             = nlist->jjnr;
129     shiftidx         = nlist->shift;
130     gid              = nlist->gid;
131     shiftvec         = fr->shift_vec[0];
132     fshift           = fr->fshift[0];
133     facel            = _mm256_set1_ps(fr->epsfac);
134     charge           = mdatoms->chargeA;
135     nvdwtype         = fr->ntype;
136     vdwparam         = fr->nbfp;
137     vdwtype          = mdatoms->typeA;
138
139     vftab            = kernel_data->table_vdw->data;
140     vftabscale       = _mm256_set1_ps(kernel_data->table_vdw->scale);
141
142     sh_ewald         = _mm256_set1_ps(fr->ic->sh_ewald);
143     beta             = _mm256_set1_ps(fr->ic->ewaldcoeff_q);
144     beta2            = _mm256_mul_ps(beta,beta);
145     beta3            = _mm256_mul_ps(beta,beta2);
146
147     ewtab            = fr->ic->tabq_coul_FDV0;
148     ewtabscale       = _mm256_set1_ps(fr->ic->tabq_scale);
149     ewtabhalfspace   = _mm256_set1_ps(0.5/fr->ic->tabq_scale);
150
151     /* Setup water-specific parameters */
152     inr              = nlist->iinr[0];
153     iq1              = _mm256_mul_ps(facel,_mm256_set1_ps(charge[inr+1]));
154     iq2              = _mm256_mul_ps(facel,_mm256_set1_ps(charge[inr+2]));
155     iq3              = _mm256_mul_ps(facel,_mm256_set1_ps(charge[inr+3]));
156     vdwioffsetptr0   = vdwparam+2*nvdwtype*vdwtype[inr+0];
157
158     /* Avoid stupid compiler warnings */
159     jnrA = jnrB = jnrC = jnrD = jnrE = jnrF = jnrG = jnrH = 0;
160     j_coord_offsetA = 0;
161     j_coord_offsetB = 0;
162     j_coord_offsetC = 0;
163     j_coord_offsetD = 0;
164     j_coord_offsetE = 0;
165     j_coord_offsetF = 0;
166     j_coord_offsetG = 0;
167     j_coord_offsetH = 0;
168
169     outeriter        = 0;
170     inneriter        = 0;
171
172     for(iidx=0;iidx<4*DIM;iidx++)
173     {
174         scratch[iidx] = 0.0;
175     }
176
177     /* Start outer loop over neighborlists */
178     for(iidx=0; iidx<nri; iidx++)
179     {
180         /* Load shift vector for this list */
181         i_shift_offset   = DIM*shiftidx[iidx];
182
183         /* Load limits for loop over neighbors */
184         j_index_start    = jindex[iidx];
185         j_index_end      = jindex[iidx+1];
186
187         /* Get outer coordinate index */
188         inr              = iinr[iidx];
189         i_coord_offset   = DIM*inr;
190
191         /* Load i particle coords and add shift vector */
192         gmx_mm256_load_shift_and_4rvec_broadcast_ps(shiftvec+i_shift_offset,x+i_coord_offset,
193                                                     &ix0,&iy0,&iz0,&ix1,&iy1,&iz1,&ix2,&iy2,&iz2,&ix3,&iy3,&iz3);
194
195         fix0             = _mm256_setzero_ps();
196         fiy0             = _mm256_setzero_ps();
197         fiz0             = _mm256_setzero_ps();
198         fix1             = _mm256_setzero_ps();
199         fiy1             = _mm256_setzero_ps();
200         fiz1             = _mm256_setzero_ps();
201         fix2             = _mm256_setzero_ps();
202         fiy2             = _mm256_setzero_ps();
203         fiz2             = _mm256_setzero_ps();
204         fix3             = _mm256_setzero_ps();
205         fiy3             = _mm256_setzero_ps();
206         fiz3             = _mm256_setzero_ps();
207
208         /* Reset potential sums */
209         velecsum         = _mm256_setzero_ps();
210         vvdwsum          = _mm256_setzero_ps();
211
212         /* Start inner kernel loop */
213         for(jidx=j_index_start; jidx<j_index_end && jjnr[jidx+7]>=0; jidx+=8)
214         {
215
216             /* Get j neighbor index, and coordinate index */
217             jnrA             = jjnr[jidx];
218             jnrB             = jjnr[jidx+1];
219             jnrC             = jjnr[jidx+2];
220             jnrD             = jjnr[jidx+3];
221             jnrE             = jjnr[jidx+4];
222             jnrF             = jjnr[jidx+5];
223             jnrG             = jjnr[jidx+6];
224             jnrH             = jjnr[jidx+7];
225             j_coord_offsetA  = DIM*jnrA;
226             j_coord_offsetB  = DIM*jnrB;
227             j_coord_offsetC  = DIM*jnrC;
228             j_coord_offsetD  = DIM*jnrD;
229             j_coord_offsetE  = DIM*jnrE;
230             j_coord_offsetF  = DIM*jnrF;
231             j_coord_offsetG  = DIM*jnrG;
232             j_coord_offsetH  = DIM*jnrH;
233
234             /* load j atom coordinates */
235             gmx_mm256_load_1rvec_8ptr_swizzle_ps(x+j_coord_offsetA,x+j_coord_offsetB,
236                                                  x+j_coord_offsetC,x+j_coord_offsetD,
237                                                  x+j_coord_offsetE,x+j_coord_offsetF,
238                                                  x+j_coord_offsetG,x+j_coord_offsetH,
239                                                  &jx0,&jy0,&jz0);
240
241             /* Calculate displacement vector */
242             dx00             = _mm256_sub_ps(ix0,jx0);
243             dy00             = _mm256_sub_ps(iy0,jy0);
244             dz00             = _mm256_sub_ps(iz0,jz0);
245             dx10             = _mm256_sub_ps(ix1,jx0);
246             dy10             = _mm256_sub_ps(iy1,jy0);
247             dz10             = _mm256_sub_ps(iz1,jz0);
248             dx20             = _mm256_sub_ps(ix2,jx0);
249             dy20             = _mm256_sub_ps(iy2,jy0);
250             dz20             = _mm256_sub_ps(iz2,jz0);
251             dx30             = _mm256_sub_ps(ix3,jx0);
252             dy30             = _mm256_sub_ps(iy3,jy0);
253             dz30             = _mm256_sub_ps(iz3,jz0);
254
255             /* Calculate squared distance and things based on it */
256             rsq00            = gmx_mm256_calc_rsq_ps(dx00,dy00,dz00);
257             rsq10            = gmx_mm256_calc_rsq_ps(dx10,dy10,dz10);
258             rsq20            = gmx_mm256_calc_rsq_ps(dx20,dy20,dz20);
259             rsq30            = gmx_mm256_calc_rsq_ps(dx30,dy30,dz30);
260
261             rinv00           = gmx_mm256_invsqrt_ps(rsq00);
262             rinv10           = gmx_mm256_invsqrt_ps(rsq10);
263             rinv20           = gmx_mm256_invsqrt_ps(rsq20);
264             rinv30           = gmx_mm256_invsqrt_ps(rsq30);
265
266             rinvsq10         = _mm256_mul_ps(rinv10,rinv10);
267             rinvsq20         = _mm256_mul_ps(rinv20,rinv20);
268             rinvsq30         = _mm256_mul_ps(rinv30,rinv30);
269
270             /* Load parameters for j particles */
271             jq0              = gmx_mm256_load_8real_swizzle_ps(charge+jnrA+0,charge+jnrB+0,
272                                                                  charge+jnrC+0,charge+jnrD+0,
273                                                                  charge+jnrE+0,charge+jnrF+0,
274                                                                  charge+jnrG+0,charge+jnrH+0);
275             vdwjidx0A        = 2*vdwtype[jnrA+0];
276             vdwjidx0B        = 2*vdwtype[jnrB+0];
277             vdwjidx0C        = 2*vdwtype[jnrC+0];
278             vdwjidx0D        = 2*vdwtype[jnrD+0];
279             vdwjidx0E        = 2*vdwtype[jnrE+0];
280             vdwjidx0F        = 2*vdwtype[jnrF+0];
281             vdwjidx0G        = 2*vdwtype[jnrG+0];
282             vdwjidx0H        = 2*vdwtype[jnrH+0];
283
284             fjx0             = _mm256_setzero_ps();
285             fjy0             = _mm256_setzero_ps();
286             fjz0             = _mm256_setzero_ps();
287
288             /**************************
289              * CALCULATE INTERACTIONS *
290              **************************/
291
292             r00              = _mm256_mul_ps(rsq00,rinv00);
293
294             /* Compute parameters for interactions between i and j atoms */
295             gmx_mm256_load_8pair_swizzle_ps(vdwioffsetptr0+vdwjidx0A,
296                                             vdwioffsetptr0+vdwjidx0B,
297                                             vdwioffsetptr0+vdwjidx0C,
298                                             vdwioffsetptr0+vdwjidx0D,
299                                             vdwioffsetptr0+vdwjidx0E,
300                                             vdwioffsetptr0+vdwjidx0F,
301                                             vdwioffsetptr0+vdwjidx0G,
302                                             vdwioffsetptr0+vdwjidx0H,
303                                             &c6_00,&c12_00);
304
305             /* Calculate table index by multiplying r with table scale and truncate to integer */
306             rt               = _mm256_mul_ps(r00,vftabscale);
307             vfitab           = _mm256_cvttps_epi32(rt);
308             vfeps            = _mm256_sub_ps(rt,_mm256_round_ps(rt, _MM_FROUND_FLOOR));
309             /*         AVX1 does not support 256-bit integer operations, so now we go to 128-bit mode... */
310             vfitab_lo        = _mm256_extractf128_si256(vfitab,0x0);
311             vfitab_hi        = _mm256_extractf128_si256(vfitab,0x1);
312             vfitab_lo        = _mm_slli_epi32(vfitab_lo,3);
313             vfitab_hi        = _mm_slli_epi32(vfitab_hi,3);
314
315             /* CUBIC SPLINE TABLE DISPERSION */
316             Y                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,0)),
317                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,0)));
318             F                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,1)),
319                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,1)));
320             G                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,2)),
321                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,2)));
322             H                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,3)),
323                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,3)));
324             GMX_MM256_HALFTRANSPOSE4_PS(Y,F,G,H);
325             Heps             = _mm256_mul_ps(vfeps,H);
326             Fp               = _mm256_add_ps(F,_mm256_mul_ps(vfeps,_mm256_add_ps(G,Heps)));
327             VV               = _mm256_add_ps(Y,_mm256_mul_ps(vfeps,Fp));
328             vvdw6            = _mm256_mul_ps(c6_00,VV);
329             FF               = _mm256_add_ps(Fp,_mm256_mul_ps(vfeps,_mm256_add_ps(G,_mm256_add_ps(Heps,Heps))));
330             fvdw6            = _mm256_mul_ps(c6_00,FF);
331
332             /* CUBIC SPLINE TABLE REPULSION */
333             vfitab_lo        = _mm_add_epi32(vfitab_lo,ifour);
334             vfitab_hi        = _mm_add_epi32(vfitab_hi,ifour);
335             Y                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,0)),
336                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,0)));
337             F                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,1)),
338                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,1)));
339             G                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,2)),
340                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,2)));
341             H                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,3)),
342                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,3)));
343             GMX_MM256_HALFTRANSPOSE4_PS(Y,F,G,H);
344             Heps             = _mm256_mul_ps(vfeps,H);
345             Fp               = _mm256_add_ps(F,_mm256_mul_ps(vfeps,_mm256_add_ps(G,Heps)));
346             VV               = _mm256_add_ps(Y,_mm256_mul_ps(vfeps,Fp));
347             vvdw12           = _mm256_mul_ps(c12_00,VV);
348             FF               = _mm256_add_ps(Fp,_mm256_mul_ps(vfeps,_mm256_add_ps(G,_mm256_add_ps(Heps,Heps))));
349             fvdw12           = _mm256_mul_ps(c12_00,FF);
350             vvdw             = _mm256_add_ps(vvdw12,vvdw6);
351             fvdw             = _mm256_xor_ps(signbit,_mm256_mul_ps(_mm256_add_ps(fvdw6,fvdw12),_mm256_mul_ps(vftabscale,rinv00)));
352
353             /* Update potential sum for this i atom from the interaction with this j atom. */
354             vvdwsum          = _mm256_add_ps(vvdwsum,vvdw);
355
356             fscal            = fvdw;
357
358             /* Calculate temporary vectorial force */
359             tx               = _mm256_mul_ps(fscal,dx00);
360             ty               = _mm256_mul_ps(fscal,dy00);
361             tz               = _mm256_mul_ps(fscal,dz00);
362
363             /* Update vectorial force */
364             fix0             = _mm256_add_ps(fix0,tx);
365             fiy0             = _mm256_add_ps(fiy0,ty);
366             fiz0             = _mm256_add_ps(fiz0,tz);
367
368             fjx0             = _mm256_add_ps(fjx0,tx);
369             fjy0             = _mm256_add_ps(fjy0,ty);
370             fjz0             = _mm256_add_ps(fjz0,tz);
371
372             /**************************
373              * CALCULATE INTERACTIONS *
374              **************************/
375
376             r10              = _mm256_mul_ps(rsq10,rinv10);
377
378             /* Compute parameters for interactions between i and j atoms */
379             qq10             = _mm256_mul_ps(iq1,jq0);
380
381             /* EWALD ELECTROSTATICS */
382             
383             /* Analytical PME correction */
384             zeta2            = _mm256_mul_ps(beta2,rsq10);
385             rinv3            = _mm256_mul_ps(rinvsq10,rinv10);
386             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
387             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
388             felec            = _mm256_mul_ps(qq10,felec);
389             pmecorrV         = gmx_mm256_pmecorrV_ps(zeta2);
390             pmecorrV         = _mm256_mul_ps(pmecorrV,beta);
391             velec            = _mm256_sub_ps(rinv10,pmecorrV);
392             velec            = _mm256_mul_ps(qq10,velec);
393             
394             /* Update potential sum for this i atom from the interaction with this j atom. */
395             velecsum         = _mm256_add_ps(velecsum,velec);
396
397             fscal            = felec;
398
399             /* Calculate temporary vectorial force */
400             tx               = _mm256_mul_ps(fscal,dx10);
401             ty               = _mm256_mul_ps(fscal,dy10);
402             tz               = _mm256_mul_ps(fscal,dz10);
403
404             /* Update vectorial force */
405             fix1             = _mm256_add_ps(fix1,tx);
406             fiy1             = _mm256_add_ps(fiy1,ty);
407             fiz1             = _mm256_add_ps(fiz1,tz);
408
409             fjx0             = _mm256_add_ps(fjx0,tx);
410             fjy0             = _mm256_add_ps(fjy0,ty);
411             fjz0             = _mm256_add_ps(fjz0,tz);
412
413             /**************************
414              * CALCULATE INTERACTIONS *
415              **************************/
416
417             r20              = _mm256_mul_ps(rsq20,rinv20);
418
419             /* Compute parameters for interactions between i and j atoms */
420             qq20             = _mm256_mul_ps(iq2,jq0);
421
422             /* EWALD ELECTROSTATICS */
423             
424             /* Analytical PME correction */
425             zeta2            = _mm256_mul_ps(beta2,rsq20);
426             rinv3            = _mm256_mul_ps(rinvsq20,rinv20);
427             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
428             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
429             felec            = _mm256_mul_ps(qq20,felec);
430             pmecorrV         = gmx_mm256_pmecorrV_ps(zeta2);
431             pmecorrV         = _mm256_mul_ps(pmecorrV,beta);
432             velec            = _mm256_sub_ps(rinv20,pmecorrV);
433             velec            = _mm256_mul_ps(qq20,velec);
434             
435             /* Update potential sum for this i atom from the interaction with this j atom. */
436             velecsum         = _mm256_add_ps(velecsum,velec);
437
438             fscal            = felec;
439
440             /* Calculate temporary vectorial force */
441             tx               = _mm256_mul_ps(fscal,dx20);
442             ty               = _mm256_mul_ps(fscal,dy20);
443             tz               = _mm256_mul_ps(fscal,dz20);
444
445             /* Update vectorial force */
446             fix2             = _mm256_add_ps(fix2,tx);
447             fiy2             = _mm256_add_ps(fiy2,ty);
448             fiz2             = _mm256_add_ps(fiz2,tz);
449
450             fjx0             = _mm256_add_ps(fjx0,tx);
451             fjy0             = _mm256_add_ps(fjy0,ty);
452             fjz0             = _mm256_add_ps(fjz0,tz);
453
454             /**************************
455              * CALCULATE INTERACTIONS *
456              **************************/
457
458             r30              = _mm256_mul_ps(rsq30,rinv30);
459
460             /* Compute parameters for interactions between i and j atoms */
461             qq30             = _mm256_mul_ps(iq3,jq0);
462
463             /* EWALD ELECTROSTATICS */
464             
465             /* Analytical PME correction */
466             zeta2            = _mm256_mul_ps(beta2,rsq30);
467             rinv3            = _mm256_mul_ps(rinvsq30,rinv30);
468             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
469             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
470             felec            = _mm256_mul_ps(qq30,felec);
471             pmecorrV         = gmx_mm256_pmecorrV_ps(zeta2);
472             pmecorrV         = _mm256_mul_ps(pmecorrV,beta);
473             velec            = _mm256_sub_ps(rinv30,pmecorrV);
474             velec            = _mm256_mul_ps(qq30,velec);
475             
476             /* Update potential sum for this i atom from the interaction with this j atom. */
477             velecsum         = _mm256_add_ps(velecsum,velec);
478
479             fscal            = felec;
480
481             /* Calculate temporary vectorial force */
482             tx               = _mm256_mul_ps(fscal,dx30);
483             ty               = _mm256_mul_ps(fscal,dy30);
484             tz               = _mm256_mul_ps(fscal,dz30);
485
486             /* Update vectorial force */
487             fix3             = _mm256_add_ps(fix3,tx);
488             fiy3             = _mm256_add_ps(fiy3,ty);
489             fiz3             = _mm256_add_ps(fiz3,tz);
490
491             fjx0             = _mm256_add_ps(fjx0,tx);
492             fjy0             = _mm256_add_ps(fjy0,ty);
493             fjz0             = _mm256_add_ps(fjz0,tz);
494
495             fjptrA             = f+j_coord_offsetA;
496             fjptrB             = f+j_coord_offsetB;
497             fjptrC             = f+j_coord_offsetC;
498             fjptrD             = f+j_coord_offsetD;
499             fjptrE             = f+j_coord_offsetE;
500             fjptrF             = f+j_coord_offsetF;
501             fjptrG             = f+j_coord_offsetG;
502             fjptrH             = f+j_coord_offsetH;
503
504             gmx_mm256_decrement_1rvec_8ptr_swizzle_ps(fjptrA,fjptrB,fjptrC,fjptrD,fjptrE,fjptrF,fjptrG,fjptrH,fjx0,fjy0,fjz0);
505
506             /* Inner loop uses 311 flops */
507         }
508
509         if(jidx<j_index_end)
510         {
511
512             /* Get j neighbor index, and coordinate index */
513             jnrlistA         = jjnr[jidx];
514             jnrlistB         = jjnr[jidx+1];
515             jnrlistC         = jjnr[jidx+2];
516             jnrlistD         = jjnr[jidx+3];
517             jnrlistE         = jjnr[jidx+4];
518             jnrlistF         = jjnr[jidx+5];
519             jnrlistG         = jjnr[jidx+6];
520             jnrlistH         = jjnr[jidx+7];
521             /* Sign of each element will be negative for non-real atoms.
522              * This mask will be 0xFFFFFFFF for dummy entries and 0x0 for real ones,
523              * so use it as val = _mm_andnot_ps(mask,val) to clear dummy entries.
524              */
525             dummy_mask = gmx_mm256_set_m128(gmx_mm_castsi128_ps(_mm_cmplt_epi32(_mm_loadu_si128((const __m128i *)(jjnr+jidx+4)),_mm_setzero_si128())),
526                                             gmx_mm_castsi128_ps(_mm_cmplt_epi32(_mm_loadu_si128((const __m128i *)(jjnr+jidx)),_mm_setzero_si128())));
527                                             
528             jnrA       = (jnrlistA>=0) ? jnrlistA : 0;
529             jnrB       = (jnrlistB>=0) ? jnrlistB : 0;
530             jnrC       = (jnrlistC>=0) ? jnrlistC : 0;
531             jnrD       = (jnrlistD>=0) ? jnrlistD : 0;
532             jnrE       = (jnrlistE>=0) ? jnrlistE : 0;
533             jnrF       = (jnrlistF>=0) ? jnrlistF : 0;
534             jnrG       = (jnrlistG>=0) ? jnrlistG : 0;
535             jnrH       = (jnrlistH>=0) ? jnrlistH : 0;
536             j_coord_offsetA  = DIM*jnrA;
537             j_coord_offsetB  = DIM*jnrB;
538             j_coord_offsetC  = DIM*jnrC;
539             j_coord_offsetD  = DIM*jnrD;
540             j_coord_offsetE  = DIM*jnrE;
541             j_coord_offsetF  = DIM*jnrF;
542             j_coord_offsetG  = DIM*jnrG;
543             j_coord_offsetH  = DIM*jnrH;
544
545             /* load j atom coordinates */
546             gmx_mm256_load_1rvec_8ptr_swizzle_ps(x+j_coord_offsetA,x+j_coord_offsetB,
547                                                  x+j_coord_offsetC,x+j_coord_offsetD,
548                                                  x+j_coord_offsetE,x+j_coord_offsetF,
549                                                  x+j_coord_offsetG,x+j_coord_offsetH,
550                                                  &jx0,&jy0,&jz0);
551
552             /* Calculate displacement vector */
553             dx00             = _mm256_sub_ps(ix0,jx0);
554             dy00             = _mm256_sub_ps(iy0,jy0);
555             dz00             = _mm256_sub_ps(iz0,jz0);
556             dx10             = _mm256_sub_ps(ix1,jx0);
557             dy10             = _mm256_sub_ps(iy1,jy0);
558             dz10             = _mm256_sub_ps(iz1,jz0);
559             dx20             = _mm256_sub_ps(ix2,jx0);
560             dy20             = _mm256_sub_ps(iy2,jy0);
561             dz20             = _mm256_sub_ps(iz2,jz0);
562             dx30             = _mm256_sub_ps(ix3,jx0);
563             dy30             = _mm256_sub_ps(iy3,jy0);
564             dz30             = _mm256_sub_ps(iz3,jz0);
565
566             /* Calculate squared distance and things based on it */
567             rsq00            = gmx_mm256_calc_rsq_ps(dx00,dy00,dz00);
568             rsq10            = gmx_mm256_calc_rsq_ps(dx10,dy10,dz10);
569             rsq20            = gmx_mm256_calc_rsq_ps(dx20,dy20,dz20);
570             rsq30            = gmx_mm256_calc_rsq_ps(dx30,dy30,dz30);
571
572             rinv00           = gmx_mm256_invsqrt_ps(rsq00);
573             rinv10           = gmx_mm256_invsqrt_ps(rsq10);
574             rinv20           = gmx_mm256_invsqrt_ps(rsq20);
575             rinv30           = gmx_mm256_invsqrt_ps(rsq30);
576
577             rinvsq10         = _mm256_mul_ps(rinv10,rinv10);
578             rinvsq20         = _mm256_mul_ps(rinv20,rinv20);
579             rinvsq30         = _mm256_mul_ps(rinv30,rinv30);
580
581             /* Load parameters for j particles */
582             jq0              = gmx_mm256_load_8real_swizzle_ps(charge+jnrA+0,charge+jnrB+0,
583                                                                  charge+jnrC+0,charge+jnrD+0,
584                                                                  charge+jnrE+0,charge+jnrF+0,
585                                                                  charge+jnrG+0,charge+jnrH+0);
586             vdwjidx0A        = 2*vdwtype[jnrA+0];
587             vdwjidx0B        = 2*vdwtype[jnrB+0];
588             vdwjidx0C        = 2*vdwtype[jnrC+0];
589             vdwjidx0D        = 2*vdwtype[jnrD+0];
590             vdwjidx0E        = 2*vdwtype[jnrE+0];
591             vdwjidx0F        = 2*vdwtype[jnrF+0];
592             vdwjidx0G        = 2*vdwtype[jnrG+0];
593             vdwjidx0H        = 2*vdwtype[jnrH+0];
594
595             fjx0             = _mm256_setzero_ps();
596             fjy0             = _mm256_setzero_ps();
597             fjz0             = _mm256_setzero_ps();
598
599             /**************************
600              * CALCULATE INTERACTIONS *
601              **************************/
602
603             r00              = _mm256_mul_ps(rsq00,rinv00);
604             r00              = _mm256_andnot_ps(dummy_mask,r00);
605
606             /* Compute parameters for interactions between i and j atoms */
607             gmx_mm256_load_8pair_swizzle_ps(vdwioffsetptr0+vdwjidx0A,
608                                             vdwioffsetptr0+vdwjidx0B,
609                                             vdwioffsetptr0+vdwjidx0C,
610                                             vdwioffsetptr0+vdwjidx0D,
611                                             vdwioffsetptr0+vdwjidx0E,
612                                             vdwioffsetptr0+vdwjidx0F,
613                                             vdwioffsetptr0+vdwjidx0G,
614                                             vdwioffsetptr0+vdwjidx0H,
615                                             &c6_00,&c12_00);
616
617             /* Calculate table index by multiplying r with table scale and truncate to integer */
618             rt               = _mm256_mul_ps(r00,vftabscale);
619             vfitab           = _mm256_cvttps_epi32(rt);
620             vfeps            = _mm256_sub_ps(rt,_mm256_round_ps(rt, _MM_FROUND_FLOOR));
621             /*         AVX1 does not support 256-bit integer operations, so now we go to 128-bit mode... */
622             vfitab_lo        = _mm256_extractf128_si256(vfitab,0x0);
623             vfitab_hi        = _mm256_extractf128_si256(vfitab,0x1);
624             vfitab_lo        = _mm_slli_epi32(vfitab_lo,3);
625             vfitab_hi        = _mm_slli_epi32(vfitab_hi,3);
626
627             /* CUBIC SPLINE TABLE DISPERSION */
628             Y                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,0)),
629                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,0)));
630             F                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,1)),
631                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,1)));
632             G                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,2)),
633                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,2)));
634             H                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,3)),
635                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,3)));
636             GMX_MM256_HALFTRANSPOSE4_PS(Y,F,G,H);
637             Heps             = _mm256_mul_ps(vfeps,H);
638             Fp               = _mm256_add_ps(F,_mm256_mul_ps(vfeps,_mm256_add_ps(G,Heps)));
639             VV               = _mm256_add_ps(Y,_mm256_mul_ps(vfeps,Fp));
640             vvdw6            = _mm256_mul_ps(c6_00,VV);
641             FF               = _mm256_add_ps(Fp,_mm256_mul_ps(vfeps,_mm256_add_ps(G,_mm256_add_ps(Heps,Heps))));
642             fvdw6            = _mm256_mul_ps(c6_00,FF);
643
644             /* CUBIC SPLINE TABLE REPULSION */
645             vfitab_lo        = _mm_add_epi32(vfitab_lo,ifour);
646             vfitab_hi        = _mm_add_epi32(vfitab_hi,ifour);
647             Y                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,0)),
648                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,0)));
649             F                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,1)),
650                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,1)));
651             G                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,2)),
652                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,2)));
653             H                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,3)),
654                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,3)));
655             GMX_MM256_HALFTRANSPOSE4_PS(Y,F,G,H);
656             Heps             = _mm256_mul_ps(vfeps,H);
657             Fp               = _mm256_add_ps(F,_mm256_mul_ps(vfeps,_mm256_add_ps(G,Heps)));
658             VV               = _mm256_add_ps(Y,_mm256_mul_ps(vfeps,Fp));
659             vvdw12           = _mm256_mul_ps(c12_00,VV);
660             FF               = _mm256_add_ps(Fp,_mm256_mul_ps(vfeps,_mm256_add_ps(G,_mm256_add_ps(Heps,Heps))));
661             fvdw12           = _mm256_mul_ps(c12_00,FF);
662             vvdw             = _mm256_add_ps(vvdw12,vvdw6);
663             fvdw             = _mm256_xor_ps(signbit,_mm256_mul_ps(_mm256_add_ps(fvdw6,fvdw12),_mm256_mul_ps(vftabscale,rinv00)));
664
665             /* Update potential sum for this i atom from the interaction with this j atom. */
666             vvdw             = _mm256_andnot_ps(dummy_mask,vvdw);
667             vvdwsum          = _mm256_add_ps(vvdwsum,vvdw);
668
669             fscal            = fvdw;
670
671             fscal            = _mm256_andnot_ps(dummy_mask,fscal);
672
673             /* Calculate temporary vectorial force */
674             tx               = _mm256_mul_ps(fscal,dx00);
675             ty               = _mm256_mul_ps(fscal,dy00);
676             tz               = _mm256_mul_ps(fscal,dz00);
677
678             /* Update vectorial force */
679             fix0             = _mm256_add_ps(fix0,tx);
680             fiy0             = _mm256_add_ps(fiy0,ty);
681             fiz0             = _mm256_add_ps(fiz0,tz);
682
683             fjx0             = _mm256_add_ps(fjx0,tx);
684             fjy0             = _mm256_add_ps(fjy0,ty);
685             fjz0             = _mm256_add_ps(fjz0,tz);
686
687             /**************************
688              * CALCULATE INTERACTIONS *
689              **************************/
690
691             r10              = _mm256_mul_ps(rsq10,rinv10);
692             r10              = _mm256_andnot_ps(dummy_mask,r10);
693
694             /* Compute parameters for interactions between i and j atoms */
695             qq10             = _mm256_mul_ps(iq1,jq0);
696
697             /* EWALD ELECTROSTATICS */
698             
699             /* Analytical PME correction */
700             zeta2            = _mm256_mul_ps(beta2,rsq10);
701             rinv3            = _mm256_mul_ps(rinvsq10,rinv10);
702             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
703             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
704             felec            = _mm256_mul_ps(qq10,felec);
705             pmecorrV         = gmx_mm256_pmecorrV_ps(zeta2);
706             pmecorrV         = _mm256_mul_ps(pmecorrV,beta);
707             velec            = _mm256_sub_ps(rinv10,pmecorrV);
708             velec            = _mm256_mul_ps(qq10,velec);
709             
710             /* Update potential sum for this i atom from the interaction with this j atom. */
711             velec            = _mm256_andnot_ps(dummy_mask,velec);
712             velecsum         = _mm256_add_ps(velecsum,velec);
713
714             fscal            = felec;
715
716             fscal            = _mm256_andnot_ps(dummy_mask,fscal);
717
718             /* Calculate temporary vectorial force */
719             tx               = _mm256_mul_ps(fscal,dx10);
720             ty               = _mm256_mul_ps(fscal,dy10);
721             tz               = _mm256_mul_ps(fscal,dz10);
722
723             /* Update vectorial force */
724             fix1             = _mm256_add_ps(fix1,tx);
725             fiy1             = _mm256_add_ps(fiy1,ty);
726             fiz1             = _mm256_add_ps(fiz1,tz);
727
728             fjx0             = _mm256_add_ps(fjx0,tx);
729             fjy0             = _mm256_add_ps(fjy0,ty);
730             fjz0             = _mm256_add_ps(fjz0,tz);
731
732             /**************************
733              * CALCULATE INTERACTIONS *
734              **************************/
735
736             r20              = _mm256_mul_ps(rsq20,rinv20);
737             r20              = _mm256_andnot_ps(dummy_mask,r20);
738
739             /* Compute parameters for interactions between i and j atoms */
740             qq20             = _mm256_mul_ps(iq2,jq0);
741
742             /* EWALD ELECTROSTATICS */
743             
744             /* Analytical PME correction */
745             zeta2            = _mm256_mul_ps(beta2,rsq20);
746             rinv3            = _mm256_mul_ps(rinvsq20,rinv20);
747             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
748             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
749             felec            = _mm256_mul_ps(qq20,felec);
750             pmecorrV         = gmx_mm256_pmecorrV_ps(zeta2);
751             pmecorrV         = _mm256_mul_ps(pmecorrV,beta);
752             velec            = _mm256_sub_ps(rinv20,pmecorrV);
753             velec            = _mm256_mul_ps(qq20,velec);
754             
755             /* Update potential sum for this i atom from the interaction with this j atom. */
756             velec            = _mm256_andnot_ps(dummy_mask,velec);
757             velecsum         = _mm256_add_ps(velecsum,velec);
758
759             fscal            = felec;
760
761             fscal            = _mm256_andnot_ps(dummy_mask,fscal);
762
763             /* Calculate temporary vectorial force */
764             tx               = _mm256_mul_ps(fscal,dx20);
765             ty               = _mm256_mul_ps(fscal,dy20);
766             tz               = _mm256_mul_ps(fscal,dz20);
767
768             /* Update vectorial force */
769             fix2             = _mm256_add_ps(fix2,tx);
770             fiy2             = _mm256_add_ps(fiy2,ty);
771             fiz2             = _mm256_add_ps(fiz2,tz);
772
773             fjx0             = _mm256_add_ps(fjx0,tx);
774             fjy0             = _mm256_add_ps(fjy0,ty);
775             fjz0             = _mm256_add_ps(fjz0,tz);
776
777             /**************************
778              * CALCULATE INTERACTIONS *
779              **************************/
780
781             r30              = _mm256_mul_ps(rsq30,rinv30);
782             r30              = _mm256_andnot_ps(dummy_mask,r30);
783
784             /* Compute parameters for interactions between i and j atoms */
785             qq30             = _mm256_mul_ps(iq3,jq0);
786
787             /* EWALD ELECTROSTATICS */
788             
789             /* Analytical PME correction */
790             zeta2            = _mm256_mul_ps(beta2,rsq30);
791             rinv3            = _mm256_mul_ps(rinvsq30,rinv30);
792             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
793             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
794             felec            = _mm256_mul_ps(qq30,felec);
795             pmecorrV         = gmx_mm256_pmecorrV_ps(zeta2);
796             pmecorrV         = _mm256_mul_ps(pmecorrV,beta);
797             velec            = _mm256_sub_ps(rinv30,pmecorrV);
798             velec            = _mm256_mul_ps(qq30,velec);
799             
800             /* Update potential sum for this i atom from the interaction with this j atom. */
801             velec            = _mm256_andnot_ps(dummy_mask,velec);
802             velecsum         = _mm256_add_ps(velecsum,velec);
803
804             fscal            = felec;
805
806             fscal            = _mm256_andnot_ps(dummy_mask,fscal);
807
808             /* Calculate temporary vectorial force */
809             tx               = _mm256_mul_ps(fscal,dx30);
810             ty               = _mm256_mul_ps(fscal,dy30);
811             tz               = _mm256_mul_ps(fscal,dz30);
812
813             /* Update vectorial force */
814             fix3             = _mm256_add_ps(fix3,tx);
815             fiy3             = _mm256_add_ps(fiy3,ty);
816             fiz3             = _mm256_add_ps(fiz3,tz);
817
818             fjx0             = _mm256_add_ps(fjx0,tx);
819             fjy0             = _mm256_add_ps(fjy0,ty);
820             fjz0             = _mm256_add_ps(fjz0,tz);
821
822             fjptrA             = (jnrlistA>=0) ? f+j_coord_offsetA : scratch;
823             fjptrB             = (jnrlistB>=0) ? f+j_coord_offsetB : scratch;
824             fjptrC             = (jnrlistC>=0) ? f+j_coord_offsetC : scratch;
825             fjptrD             = (jnrlistD>=0) ? f+j_coord_offsetD : scratch;
826             fjptrE             = (jnrlistE>=0) ? f+j_coord_offsetE : scratch;
827             fjptrF             = (jnrlistF>=0) ? f+j_coord_offsetF : scratch;
828             fjptrG             = (jnrlistG>=0) ? f+j_coord_offsetG : scratch;
829             fjptrH             = (jnrlistH>=0) ? f+j_coord_offsetH : scratch;
830
831             gmx_mm256_decrement_1rvec_8ptr_swizzle_ps(fjptrA,fjptrB,fjptrC,fjptrD,fjptrE,fjptrF,fjptrG,fjptrH,fjx0,fjy0,fjz0);
832
833             /* Inner loop uses 315 flops */
834         }
835
836         /* End of innermost loop */
837
838         gmx_mm256_update_iforce_4atom_swizzle_ps(fix0,fiy0,fiz0,fix1,fiy1,fiz1,fix2,fiy2,fiz2,fix3,fiy3,fiz3,
839                                                  f+i_coord_offset,fshift+i_shift_offset);
840
841         ggid                        = gid[iidx];
842         /* Update potential energies */
843         gmx_mm256_update_1pot_ps(velecsum,kernel_data->energygrp_elec+ggid);
844         gmx_mm256_update_1pot_ps(vvdwsum,kernel_data->energygrp_vdw+ggid);
845
846         /* Increment number of inner iterations */
847         inneriter                  += j_index_end - j_index_start;
848
849         /* Outer loop uses 26 flops */
850     }
851
852     /* Increment number of outer iterations */
853     outeriter        += nri;
854
855     /* Update outer/inner flops */
856
857     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_VDW_W4_VF,outeriter*26 + inneriter*315);
858 }
859 /*
860  * Gromacs nonbonded kernel:   nb_kernel_ElecEw_VdwCSTab_GeomW4P1_F_avx_256_single
861  * Electrostatics interaction: Ewald
862  * VdW interaction:            CubicSplineTable
863  * Geometry:                   Water4-Particle
864  * Calculate force/pot:        Force
865  */
866 void
867 nb_kernel_ElecEw_VdwCSTab_GeomW4P1_F_avx_256_single
868                     (t_nblist                    * gmx_restrict       nlist,
869                      rvec                        * gmx_restrict          xx,
870                      rvec                        * gmx_restrict          ff,
871                      t_forcerec                  * gmx_restrict          fr,
872                      t_mdatoms                   * gmx_restrict     mdatoms,
873                      nb_kernel_data_t gmx_unused * gmx_restrict kernel_data,
874                      t_nrnb                      * gmx_restrict        nrnb)
875 {
876     /* Suffixes 0,1,2,3 refer to particle indices for waters in the inner or outer loop, or 
877      * just 0 for non-waters.
878      * Suffixes A,B,C,D,E,F,G,H refer to j loop unrolling done with AVX, e.g. for the eight different
879      * jnr indices corresponding to data put in the four positions in the SIMD register.
880      */
881     int              i_shift_offset,i_coord_offset,outeriter,inneriter;
882     int              j_index_start,j_index_end,jidx,nri,inr,ggid,iidx;
883     int              jnrA,jnrB,jnrC,jnrD;
884     int              jnrE,jnrF,jnrG,jnrH;
885     int              jnrlistA,jnrlistB,jnrlistC,jnrlistD;
886     int              jnrlistE,jnrlistF,jnrlistG,jnrlistH;
887     int              j_coord_offsetA,j_coord_offsetB,j_coord_offsetC,j_coord_offsetD;
888     int              j_coord_offsetE,j_coord_offsetF,j_coord_offsetG,j_coord_offsetH;
889     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
890     real             rcutoff_scalar;
891     real             *shiftvec,*fshift,*x,*f;
892     real             *fjptrA,*fjptrB,*fjptrC,*fjptrD,*fjptrE,*fjptrF,*fjptrG,*fjptrH;
893     real             scratch[4*DIM];
894     __m256           tx,ty,tz,fscal,rcutoff,rcutoff2,jidxall;
895     real *           vdwioffsetptr0;
896     __m256           ix0,iy0,iz0,fix0,fiy0,fiz0,iq0,isai0;
897     real *           vdwioffsetptr1;
898     __m256           ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
899     real *           vdwioffsetptr2;
900     __m256           ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
901     real *           vdwioffsetptr3;
902     __m256           ix3,iy3,iz3,fix3,fiy3,fiz3,iq3,isai3;
903     int              vdwjidx0A,vdwjidx0B,vdwjidx0C,vdwjidx0D,vdwjidx0E,vdwjidx0F,vdwjidx0G,vdwjidx0H;
904     __m256           jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
905     __m256           dx00,dy00,dz00,rsq00,rinv00,rinvsq00,r00,qq00,c6_00,c12_00;
906     __m256           dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10;
907     __m256           dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20;
908     __m256           dx30,dy30,dz30,rsq30,rinv30,rinvsq30,r30,qq30,c6_30,c12_30;
909     __m256           velec,felec,velecsum,facel,crf,krf,krf2;
910     real             *charge;
911     int              nvdwtype;
912     __m256           rinvsix,rvdw,vvdw,vvdw6,vvdw12,fvdw,fvdw6,fvdw12,vvdwsum,sh_vdw_invrcut6;
913     int              *vdwtype;
914     real             *vdwparam;
915     __m256           one_sixth   = _mm256_set1_ps(1.0/6.0);
916     __m256           one_twelfth = _mm256_set1_ps(1.0/12.0);
917     __m256i          vfitab;
918     __m128i          vfitab_lo,vfitab_hi;
919     __m128i          ifour       = _mm_set1_epi32(4);
920     __m256           rt,vfeps,vftabscale,Y,F,G,H,Heps,Fp,VV,FF;
921     real             *vftab;
922     __m256i          ewitab;
923     __m128i          ewitab_lo,ewitab_hi;
924     __m256           ewtabscale,eweps,sh_ewald,ewrt,ewtabhalfspace,ewtabF,ewtabFn,ewtabD,ewtabV;
925     __m256           beta,beta2,beta3,zeta2,pmecorrF,pmecorrV,rinv3;
926     real             *ewtab;
927     __m256           dummy_mask,cutoff_mask;
928     __m256           signbit = _mm256_castsi256_ps( _mm256_set1_epi32(0x80000000) );
929     __m256           one     = _mm256_set1_ps(1.0);
930     __m256           two     = _mm256_set1_ps(2.0);
931     x                = xx[0];
932     f                = ff[0];
933
934     nri              = nlist->nri;
935     iinr             = nlist->iinr;
936     jindex           = nlist->jindex;
937     jjnr             = nlist->jjnr;
938     shiftidx         = nlist->shift;
939     gid              = nlist->gid;
940     shiftvec         = fr->shift_vec[0];
941     fshift           = fr->fshift[0];
942     facel            = _mm256_set1_ps(fr->epsfac);
943     charge           = mdatoms->chargeA;
944     nvdwtype         = fr->ntype;
945     vdwparam         = fr->nbfp;
946     vdwtype          = mdatoms->typeA;
947
948     vftab            = kernel_data->table_vdw->data;
949     vftabscale       = _mm256_set1_ps(kernel_data->table_vdw->scale);
950
951     sh_ewald         = _mm256_set1_ps(fr->ic->sh_ewald);
952     beta             = _mm256_set1_ps(fr->ic->ewaldcoeff_q);
953     beta2            = _mm256_mul_ps(beta,beta);
954     beta3            = _mm256_mul_ps(beta,beta2);
955
956     ewtab            = fr->ic->tabq_coul_F;
957     ewtabscale       = _mm256_set1_ps(fr->ic->tabq_scale);
958     ewtabhalfspace   = _mm256_set1_ps(0.5/fr->ic->tabq_scale);
959
960     /* Setup water-specific parameters */
961     inr              = nlist->iinr[0];
962     iq1              = _mm256_mul_ps(facel,_mm256_set1_ps(charge[inr+1]));
963     iq2              = _mm256_mul_ps(facel,_mm256_set1_ps(charge[inr+2]));
964     iq3              = _mm256_mul_ps(facel,_mm256_set1_ps(charge[inr+3]));
965     vdwioffsetptr0   = vdwparam+2*nvdwtype*vdwtype[inr+0];
966
967     /* Avoid stupid compiler warnings */
968     jnrA = jnrB = jnrC = jnrD = jnrE = jnrF = jnrG = jnrH = 0;
969     j_coord_offsetA = 0;
970     j_coord_offsetB = 0;
971     j_coord_offsetC = 0;
972     j_coord_offsetD = 0;
973     j_coord_offsetE = 0;
974     j_coord_offsetF = 0;
975     j_coord_offsetG = 0;
976     j_coord_offsetH = 0;
977
978     outeriter        = 0;
979     inneriter        = 0;
980
981     for(iidx=0;iidx<4*DIM;iidx++)
982     {
983         scratch[iidx] = 0.0;
984     }
985
986     /* Start outer loop over neighborlists */
987     for(iidx=0; iidx<nri; iidx++)
988     {
989         /* Load shift vector for this list */
990         i_shift_offset   = DIM*shiftidx[iidx];
991
992         /* Load limits for loop over neighbors */
993         j_index_start    = jindex[iidx];
994         j_index_end      = jindex[iidx+1];
995
996         /* Get outer coordinate index */
997         inr              = iinr[iidx];
998         i_coord_offset   = DIM*inr;
999
1000         /* Load i particle coords and add shift vector */
1001         gmx_mm256_load_shift_and_4rvec_broadcast_ps(shiftvec+i_shift_offset,x+i_coord_offset,
1002                                                     &ix0,&iy0,&iz0,&ix1,&iy1,&iz1,&ix2,&iy2,&iz2,&ix3,&iy3,&iz3);
1003
1004         fix0             = _mm256_setzero_ps();
1005         fiy0             = _mm256_setzero_ps();
1006         fiz0             = _mm256_setzero_ps();
1007         fix1             = _mm256_setzero_ps();
1008         fiy1             = _mm256_setzero_ps();
1009         fiz1             = _mm256_setzero_ps();
1010         fix2             = _mm256_setzero_ps();
1011         fiy2             = _mm256_setzero_ps();
1012         fiz2             = _mm256_setzero_ps();
1013         fix3             = _mm256_setzero_ps();
1014         fiy3             = _mm256_setzero_ps();
1015         fiz3             = _mm256_setzero_ps();
1016
1017         /* Start inner kernel loop */
1018         for(jidx=j_index_start; jidx<j_index_end && jjnr[jidx+7]>=0; jidx+=8)
1019         {
1020
1021             /* Get j neighbor index, and coordinate index */
1022             jnrA             = jjnr[jidx];
1023             jnrB             = jjnr[jidx+1];
1024             jnrC             = jjnr[jidx+2];
1025             jnrD             = jjnr[jidx+3];
1026             jnrE             = jjnr[jidx+4];
1027             jnrF             = jjnr[jidx+5];
1028             jnrG             = jjnr[jidx+6];
1029             jnrH             = jjnr[jidx+7];
1030             j_coord_offsetA  = DIM*jnrA;
1031             j_coord_offsetB  = DIM*jnrB;
1032             j_coord_offsetC  = DIM*jnrC;
1033             j_coord_offsetD  = DIM*jnrD;
1034             j_coord_offsetE  = DIM*jnrE;
1035             j_coord_offsetF  = DIM*jnrF;
1036             j_coord_offsetG  = DIM*jnrG;
1037             j_coord_offsetH  = DIM*jnrH;
1038
1039             /* load j atom coordinates */
1040             gmx_mm256_load_1rvec_8ptr_swizzle_ps(x+j_coord_offsetA,x+j_coord_offsetB,
1041                                                  x+j_coord_offsetC,x+j_coord_offsetD,
1042                                                  x+j_coord_offsetE,x+j_coord_offsetF,
1043                                                  x+j_coord_offsetG,x+j_coord_offsetH,
1044                                                  &jx0,&jy0,&jz0);
1045
1046             /* Calculate displacement vector */
1047             dx00             = _mm256_sub_ps(ix0,jx0);
1048             dy00             = _mm256_sub_ps(iy0,jy0);
1049             dz00             = _mm256_sub_ps(iz0,jz0);
1050             dx10             = _mm256_sub_ps(ix1,jx0);
1051             dy10             = _mm256_sub_ps(iy1,jy0);
1052             dz10             = _mm256_sub_ps(iz1,jz0);
1053             dx20             = _mm256_sub_ps(ix2,jx0);
1054             dy20             = _mm256_sub_ps(iy2,jy0);
1055             dz20             = _mm256_sub_ps(iz2,jz0);
1056             dx30             = _mm256_sub_ps(ix3,jx0);
1057             dy30             = _mm256_sub_ps(iy3,jy0);
1058             dz30             = _mm256_sub_ps(iz3,jz0);
1059
1060             /* Calculate squared distance and things based on it */
1061             rsq00            = gmx_mm256_calc_rsq_ps(dx00,dy00,dz00);
1062             rsq10            = gmx_mm256_calc_rsq_ps(dx10,dy10,dz10);
1063             rsq20            = gmx_mm256_calc_rsq_ps(dx20,dy20,dz20);
1064             rsq30            = gmx_mm256_calc_rsq_ps(dx30,dy30,dz30);
1065
1066             rinv00           = gmx_mm256_invsqrt_ps(rsq00);
1067             rinv10           = gmx_mm256_invsqrt_ps(rsq10);
1068             rinv20           = gmx_mm256_invsqrt_ps(rsq20);
1069             rinv30           = gmx_mm256_invsqrt_ps(rsq30);
1070
1071             rinvsq10         = _mm256_mul_ps(rinv10,rinv10);
1072             rinvsq20         = _mm256_mul_ps(rinv20,rinv20);
1073             rinvsq30         = _mm256_mul_ps(rinv30,rinv30);
1074
1075             /* Load parameters for j particles */
1076             jq0              = gmx_mm256_load_8real_swizzle_ps(charge+jnrA+0,charge+jnrB+0,
1077                                                                  charge+jnrC+0,charge+jnrD+0,
1078                                                                  charge+jnrE+0,charge+jnrF+0,
1079                                                                  charge+jnrG+0,charge+jnrH+0);
1080             vdwjidx0A        = 2*vdwtype[jnrA+0];
1081             vdwjidx0B        = 2*vdwtype[jnrB+0];
1082             vdwjidx0C        = 2*vdwtype[jnrC+0];
1083             vdwjidx0D        = 2*vdwtype[jnrD+0];
1084             vdwjidx0E        = 2*vdwtype[jnrE+0];
1085             vdwjidx0F        = 2*vdwtype[jnrF+0];
1086             vdwjidx0G        = 2*vdwtype[jnrG+0];
1087             vdwjidx0H        = 2*vdwtype[jnrH+0];
1088
1089             fjx0             = _mm256_setzero_ps();
1090             fjy0             = _mm256_setzero_ps();
1091             fjz0             = _mm256_setzero_ps();
1092
1093             /**************************
1094              * CALCULATE INTERACTIONS *
1095              **************************/
1096
1097             r00              = _mm256_mul_ps(rsq00,rinv00);
1098
1099             /* Compute parameters for interactions between i and j atoms */
1100             gmx_mm256_load_8pair_swizzle_ps(vdwioffsetptr0+vdwjidx0A,
1101                                             vdwioffsetptr0+vdwjidx0B,
1102                                             vdwioffsetptr0+vdwjidx0C,
1103                                             vdwioffsetptr0+vdwjidx0D,
1104                                             vdwioffsetptr0+vdwjidx0E,
1105                                             vdwioffsetptr0+vdwjidx0F,
1106                                             vdwioffsetptr0+vdwjidx0G,
1107                                             vdwioffsetptr0+vdwjidx0H,
1108                                             &c6_00,&c12_00);
1109
1110             /* Calculate table index by multiplying r with table scale and truncate to integer */
1111             rt               = _mm256_mul_ps(r00,vftabscale);
1112             vfitab           = _mm256_cvttps_epi32(rt);
1113             vfeps            = _mm256_sub_ps(rt,_mm256_round_ps(rt, _MM_FROUND_FLOOR));
1114             /*         AVX1 does not support 256-bit integer operations, so now we go to 128-bit mode... */
1115             vfitab_lo        = _mm256_extractf128_si256(vfitab,0x0);
1116             vfitab_hi        = _mm256_extractf128_si256(vfitab,0x1);
1117             vfitab_lo        = _mm_slli_epi32(vfitab_lo,3);
1118             vfitab_hi        = _mm_slli_epi32(vfitab_hi,3);
1119
1120             /* CUBIC SPLINE TABLE DISPERSION */
1121             Y                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,0)),
1122                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,0)));
1123             F                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,1)),
1124                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,1)));
1125             G                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,2)),
1126                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,2)));
1127             H                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,3)),
1128                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,3)));
1129             GMX_MM256_HALFTRANSPOSE4_PS(Y,F,G,H);
1130             Heps             = _mm256_mul_ps(vfeps,H);
1131             Fp               = _mm256_add_ps(F,_mm256_mul_ps(vfeps,_mm256_add_ps(G,Heps)));
1132             FF               = _mm256_add_ps(Fp,_mm256_mul_ps(vfeps,_mm256_add_ps(G,_mm256_add_ps(Heps,Heps))));
1133             fvdw6            = _mm256_mul_ps(c6_00,FF);
1134
1135             /* CUBIC SPLINE TABLE REPULSION */
1136             vfitab_lo        = _mm_add_epi32(vfitab_lo,ifour);
1137             vfitab_hi        = _mm_add_epi32(vfitab_hi,ifour);
1138             Y                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,0)),
1139                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,0)));
1140             F                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,1)),
1141                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,1)));
1142             G                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,2)),
1143                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,2)));
1144             H                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,3)),
1145                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,3)));
1146             GMX_MM256_HALFTRANSPOSE4_PS(Y,F,G,H);
1147             Heps             = _mm256_mul_ps(vfeps,H);
1148             Fp               = _mm256_add_ps(F,_mm256_mul_ps(vfeps,_mm256_add_ps(G,Heps)));
1149             FF               = _mm256_add_ps(Fp,_mm256_mul_ps(vfeps,_mm256_add_ps(G,_mm256_add_ps(Heps,Heps))));
1150             fvdw12           = _mm256_mul_ps(c12_00,FF);
1151             fvdw             = _mm256_xor_ps(signbit,_mm256_mul_ps(_mm256_add_ps(fvdw6,fvdw12),_mm256_mul_ps(vftabscale,rinv00)));
1152
1153             fscal            = fvdw;
1154
1155             /* Calculate temporary vectorial force */
1156             tx               = _mm256_mul_ps(fscal,dx00);
1157             ty               = _mm256_mul_ps(fscal,dy00);
1158             tz               = _mm256_mul_ps(fscal,dz00);
1159
1160             /* Update vectorial force */
1161             fix0             = _mm256_add_ps(fix0,tx);
1162             fiy0             = _mm256_add_ps(fiy0,ty);
1163             fiz0             = _mm256_add_ps(fiz0,tz);
1164
1165             fjx0             = _mm256_add_ps(fjx0,tx);
1166             fjy0             = _mm256_add_ps(fjy0,ty);
1167             fjz0             = _mm256_add_ps(fjz0,tz);
1168
1169             /**************************
1170              * CALCULATE INTERACTIONS *
1171              **************************/
1172
1173             r10              = _mm256_mul_ps(rsq10,rinv10);
1174
1175             /* Compute parameters for interactions between i and j atoms */
1176             qq10             = _mm256_mul_ps(iq1,jq0);
1177
1178             /* EWALD ELECTROSTATICS */
1179             
1180             /* Analytical PME correction */
1181             zeta2            = _mm256_mul_ps(beta2,rsq10);
1182             rinv3            = _mm256_mul_ps(rinvsq10,rinv10);
1183             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
1184             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
1185             felec            = _mm256_mul_ps(qq10,felec);
1186             
1187             fscal            = felec;
1188
1189             /* Calculate temporary vectorial force */
1190             tx               = _mm256_mul_ps(fscal,dx10);
1191             ty               = _mm256_mul_ps(fscal,dy10);
1192             tz               = _mm256_mul_ps(fscal,dz10);
1193
1194             /* Update vectorial force */
1195             fix1             = _mm256_add_ps(fix1,tx);
1196             fiy1             = _mm256_add_ps(fiy1,ty);
1197             fiz1             = _mm256_add_ps(fiz1,tz);
1198
1199             fjx0             = _mm256_add_ps(fjx0,tx);
1200             fjy0             = _mm256_add_ps(fjy0,ty);
1201             fjz0             = _mm256_add_ps(fjz0,tz);
1202
1203             /**************************
1204              * CALCULATE INTERACTIONS *
1205              **************************/
1206
1207             r20              = _mm256_mul_ps(rsq20,rinv20);
1208
1209             /* Compute parameters for interactions between i and j atoms */
1210             qq20             = _mm256_mul_ps(iq2,jq0);
1211
1212             /* EWALD ELECTROSTATICS */
1213             
1214             /* Analytical PME correction */
1215             zeta2            = _mm256_mul_ps(beta2,rsq20);
1216             rinv3            = _mm256_mul_ps(rinvsq20,rinv20);
1217             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
1218             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
1219             felec            = _mm256_mul_ps(qq20,felec);
1220             
1221             fscal            = felec;
1222
1223             /* Calculate temporary vectorial force */
1224             tx               = _mm256_mul_ps(fscal,dx20);
1225             ty               = _mm256_mul_ps(fscal,dy20);
1226             tz               = _mm256_mul_ps(fscal,dz20);
1227
1228             /* Update vectorial force */
1229             fix2             = _mm256_add_ps(fix2,tx);
1230             fiy2             = _mm256_add_ps(fiy2,ty);
1231             fiz2             = _mm256_add_ps(fiz2,tz);
1232
1233             fjx0             = _mm256_add_ps(fjx0,tx);
1234             fjy0             = _mm256_add_ps(fjy0,ty);
1235             fjz0             = _mm256_add_ps(fjz0,tz);
1236
1237             /**************************
1238              * CALCULATE INTERACTIONS *
1239              **************************/
1240
1241             r30              = _mm256_mul_ps(rsq30,rinv30);
1242
1243             /* Compute parameters for interactions between i and j atoms */
1244             qq30             = _mm256_mul_ps(iq3,jq0);
1245
1246             /* EWALD ELECTROSTATICS */
1247             
1248             /* Analytical PME correction */
1249             zeta2            = _mm256_mul_ps(beta2,rsq30);
1250             rinv3            = _mm256_mul_ps(rinvsq30,rinv30);
1251             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
1252             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
1253             felec            = _mm256_mul_ps(qq30,felec);
1254             
1255             fscal            = felec;
1256
1257             /* Calculate temporary vectorial force */
1258             tx               = _mm256_mul_ps(fscal,dx30);
1259             ty               = _mm256_mul_ps(fscal,dy30);
1260             tz               = _mm256_mul_ps(fscal,dz30);
1261
1262             /* Update vectorial force */
1263             fix3             = _mm256_add_ps(fix3,tx);
1264             fiy3             = _mm256_add_ps(fiy3,ty);
1265             fiz3             = _mm256_add_ps(fiz3,tz);
1266
1267             fjx0             = _mm256_add_ps(fjx0,tx);
1268             fjy0             = _mm256_add_ps(fjy0,ty);
1269             fjz0             = _mm256_add_ps(fjz0,tz);
1270
1271             fjptrA             = f+j_coord_offsetA;
1272             fjptrB             = f+j_coord_offsetB;
1273             fjptrC             = f+j_coord_offsetC;
1274             fjptrD             = f+j_coord_offsetD;
1275             fjptrE             = f+j_coord_offsetE;
1276             fjptrF             = f+j_coord_offsetF;
1277             fjptrG             = f+j_coord_offsetG;
1278             fjptrH             = f+j_coord_offsetH;
1279
1280             gmx_mm256_decrement_1rvec_8ptr_swizzle_ps(fjptrA,fjptrB,fjptrC,fjptrD,fjptrE,fjptrF,fjptrG,fjptrH,fjx0,fjy0,fjz0);
1281
1282             /* Inner loop uses 219 flops */
1283         }
1284
1285         if(jidx<j_index_end)
1286         {
1287
1288             /* Get j neighbor index, and coordinate index */
1289             jnrlistA         = jjnr[jidx];
1290             jnrlistB         = jjnr[jidx+1];
1291             jnrlistC         = jjnr[jidx+2];
1292             jnrlistD         = jjnr[jidx+3];
1293             jnrlistE         = jjnr[jidx+4];
1294             jnrlistF         = jjnr[jidx+5];
1295             jnrlistG         = jjnr[jidx+6];
1296             jnrlistH         = jjnr[jidx+7];
1297             /* Sign of each element will be negative for non-real atoms.
1298              * This mask will be 0xFFFFFFFF for dummy entries and 0x0 for real ones,
1299              * so use it as val = _mm_andnot_ps(mask,val) to clear dummy entries.
1300              */
1301             dummy_mask = gmx_mm256_set_m128(gmx_mm_castsi128_ps(_mm_cmplt_epi32(_mm_loadu_si128((const __m128i *)(jjnr+jidx+4)),_mm_setzero_si128())),
1302                                             gmx_mm_castsi128_ps(_mm_cmplt_epi32(_mm_loadu_si128((const __m128i *)(jjnr+jidx)),_mm_setzero_si128())));
1303                                             
1304             jnrA       = (jnrlistA>=0) ? jnrlistA : 0;
1305             jnrB       = (jnrlistB>=0) ? jnrlistB : 0;
1306             jnrC       = (jnrlistC>=0) ? jnrlistC : 0;
1307             jnrD       = (jnrlistD>=0) ? jnrlistD : 0;
1308             jnrE       = (jnrlistE>=0) ? jnrlistE : 0;
1309             jnrF       = (jnrlistF>=0) ? jnrlistF : 0;
1310             jnrG       = (jnrlistG>=0) ? jnrlistG : 0;
1311             jnrH       = (jnrlistH>=0) ? jnrlistH : 0;
1312             j_coord_offsetA  = DIM*jnrA;
1313             j_coord_offsetB  = DIM*jnrB;
1314             j_coord_offsetC  = DIM*jnrC;
1315             j_coord_offsetD  = DIM*jnrD;
1316             j_coord_offsetE  = DIM*jnrE;
1317             j_coord_offsetF  = DIM*jnrF;
1318             j_coord_offsetG  = DIM*jnrG;
1319             j_coord_offsetH  = DIM*jnrH;
1320
1321             /* load j atom coordinates */
1322             gmx_mm256_load_1rvec_8ptr_swizzle_ps(x+j_coord_offsetA,x+j_coord_offsetB,
1323                                                  x+j_coord_offsetC,x+j_coord_offsetD,
1324                                                  x+j_coord_offsetE,x+j_coord_offsetF,
1325                                                  x+j_coord_offsetG,x+j_coord_offsetH,
1326                                                  &jx0,&jy0,&jz0);
1327
1328             /* Calculate displacement vector */
1329             dx00             = _mm256_sub_ps(ix0,jx0);
1330             dy00             = _mm256_sub_ps(iy0,jy0);
1331             dz00             = _mm256_sub_ps(iz0,jz0);
1332             dx10             = _mm256_sub_ps(ix1,jx0);
1333             dy10             = _mm256_sub_ps(iy1,jy0);
1334             dz10             = _mm256_sub_ps(iz1,jz0);
1335             dx20             = _mm256_sub_ps(ix2,jx0);
1336             dy20             = _mm256_sub_ps(iy2,jy0);
1337             dz20             = _mm256_sub_ps(iz2,jz0);
1338             dx30             = _mm256_sub_ps(ix3,jx0);
1339             dy30             = _mm256_sub_ps(iy3,jy0);
1340             dz30             = _mm256_sub_ps(iz3,jz0);
1341
1342             /* Calculate squared distance and things based on it */
1343             rsq00            = gmx_mm256_calc_rsq_ps(dx00,dy00,dz00);
1344             rsq10            = gmx_mm256_calc_rsq_ps(dx10,dy10,dz10);
1345             rsq20            = gmx_mm256_calc_rsq_ps(dx20,dy20,dz20);
1346             rsq30            = gmx_mm256_calc_rsq_ps(dx30,dy30,dz30);
1347
1348             rinv00           = gmx_mm256_invsqrt_ps(rsq00);
1349             rinv10           = gmx_mm256_invsqrt_ps(rsq10);
1350             rinv20           = gmx_mm256_invsqrt_ps(rsq20);
1351             rinv30           = gmx_mm256_invsqrt_ps(rsq30);
1352
1353             rinvsq10         = _mm256_mul_ps(rinv10,rinv10);
1354             rinvsq20         = _mm256_mul_ps(rinv20,rinv20);
1355             rinvsq30         = _mm256_mul_ps(rinv30,rinv30);
1356
1357             /* Load parameters for j particles */
1358             jq0              = gmx_mm256_load_8real_swizzle_ps(charge+jnrA+0,charge+jnrB+0,
1359                                                                  charge+jnrC+0,charge+jnrD+0,
1360                                                                  charge+jnrE+0,charge+jnrF+0,
1361                                                                  charge+jnrG+0,charge+jnrH+0);
1362             vdwjidx0A        = 2*vdwtype[jnrA+0];
1363             vdwjidx0B        = 2*vdwtype[jnrB+0];
1364             vdwjidx0C        = 2*vdwtype[jnrC+0];
1365             vdwjidx0D        = 2*vdwtype[jnrD+0];
1366             vdwjidx0E        = 2*vdwtype[jnrE+0];
1367             vdwjidx0F        = 2*vdwtype[jnrF+0];
1368             vdwjidx0G        = 2*vdwtype[jnrG+0];
1369             vdwjidx0H        = 2*vdwtype[jnrH+0];
1370
1371             fjx0             = _mm256_setzero_ps();
1372             fjy0             = _mm256_setzero_ps();
1373             fjz0             = _mm256_setzero_ps();
1374
1375             /**************************
1376              * CALCULATE INTERACTIONS *
1377              **************************/
1378
1379             r00              = _mm256_mul_ps(rsq00,rinv00);
1380             r00              = _mm256_andnot_ps(dummy_mask,r00);
1381
1382             /* Compute parameters for interactions between i and j atoms */
1383             gmx_mm256_load_8pair_swizzle_ps(vdwioffsetptr0+vdwjidx0A,
1384                                             vdwioffsetptr0+vdwjidx0B,
1385                                             vdwioffsetptr0+vdwjidx0C,
1386                                             vdwioffsetptr0+vdwjidx0D,
1387                                             vdwioffsetptr0+vdwjidx0E,
1388                                             vdwioffsetptr0+vdwjidx0F,
1389                                             vdwioffsetptr0+vdwjidx0G,
1390                                             vdwioffsetptr0+vdwjidx0H,
1391                                             &c6_00,&c12_00);
1392
1393             /* Calculate table index by multiplying r with table scale and truncate to integer */
1394             rt               = _mm256_mul_ps(r00,vftabscale);
1395             vfitab           = _mm256_cvttps_epi32(rt);
1396             vfeps            = _mm256_sub_ps(rt,_mm256_round_ps(rt, _MM_FROUND_FLOOR));
1397             /*         AVX1 does not support 256-bit integer operations, so now we go to 128-bit mode... */
1398             vfitab_lo        = _mm256_extractf128_si256(vfitab,0x0);
1399             vfitab_hi        = _mm256_extractf128_si256(vfitab,0x1);
1400             vfitab_lo        = _mm_slli_epi32(vfitab_lo,3);
1401             vfitab_hi        = _mm_slli_epi32(vfitab_hi,3);
1402
1403             /* CUBIC SPLINE TABLE DISPERSION */
1404             Y                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,0)),
1405                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,0)));
1406             F                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,1)),
1407                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,1)));
1408             G                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,2)),
1409                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,2)));
1410             H                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,3)),
1411                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,3)));
1412             GMX_MM256_HALFTRANSPOSE4_PS(Y,F,G,H);
1413             Heps             = _mm256_mul_ps(vfeps,H);
1414             Fp               = _mm256_add_ps(F,_mm256_mul_ps(vfeps,_mm256_add_ps(G,Heps)));
1415             FF               = _mm256_add_ps(Fp,_mm256_mul_ps(vfeps,_mm256_add_ps(G,_mm256_add_ps(Heps,Heps))));
1416             fvdw6            = _mm256_mul_ps(c6_00,FF);
1417
1418             /* CUBIC SPLINE TABLE REPULSION */
1419             vfitab_lo        = _mm_add_epi32(vfitab_lo,ifour);
1420             vfitab_hi        = _mm_add_epi32(vfitab_hi,ifour);
1421             Y                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,0)),
1422                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,0)));
1423             F                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,1)),
1424                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,1)));
1425             G                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,2)),
1426                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,2)));
1427             H                = gmx_mm256_set_m128(_mm_load_ps(vftab + _mm_extract_epi32(vfitab_hi,3)),
1428                                                   _mm_load_ps(vftab + _mm_extract_epi32(vfitab_lo,3)));
1429             GMX_MM256_HALFTRANSPOSE4_PS(Y,F,G,H);
1430             Heps             = _mm256_mul_ps(vfeps,H);
1431             Fp               = _mm256_add_ps(F,_mm256_mul_ps(vfeps,_mm256_add_ps(G,Heps)));
1432             FF               = _mm256_add_ps(Fp,_mm256_mul_ps(vfeps,_mm256_add_ps(G,_mm256_add_ps(Heps,Heps))));
1433             fvdw12           = _mm256_mul_ps(c12_00,FF);
1434             fvdw             = _mm256_xor_ps(signbit,_mm256_mul_ps(_mm256_add_ps(fvdw6,fvdw12),_mm256_mul_ps(vftabscale,rinv00)));
1435
1436             fscal            = fvdw;
1437
1438             fscal            = _mm256_andnot_ps(dummy_mask,fscal);
1439
1440             /* Calculate temporary vectorial force */
1441             tx               = _mm256_mul_ps(fscal,dx00);
1442             ty               = _mm256_mul_ps(fscal,dy00);
1443             tz               = _mm256_mul_ps(fscal,dz00);
1444
1445             /* Update vectorial force */
1446             fix0             = _mm256_add_ps(fix0,tx);
1447             fiy0             = _mm256_add_ps(fiy0,ty);
1448             fiz0             = _mm256_add_ps(fiz0,tz);
1449
1450             fjx0             = _mm256_add_ps(fjx0,tx);
1451             fjy0             = _mm256_add_ps(fjy0,ty);
1452             fjz0             = _mm256_add_ps(fjz0,tz);
1453
1454             /**************************
1455              * CALCULATE INTERACTIONS *
1456              **************************/
1457
1458             r10              = _mm256_mul_ps(rsq10,rinv10);
1459             r10              = _mm256_andnot_ps(dummy_mask,r10);
1460
1461             /* Compute parameters for interactions between i and j atoms */
1462             qq10             = _mm256_mul_ps(iq1,jq0);
1463
1464             /* EWALD ELECTROSTATICS */
1465             
1466             /* Analytical PME correction */
1467             zeta2            = _mm256_mul_ps(beta2,rsq10);
1468             rinv3            = _mm256_mul_ps(rinvsq10,rinv10);
1469             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
1470             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
1471             felec            = _mm256_mul_ps(qq10,felec);
1472             
1473             fscal            = felec;
1474
1475             fscal            = _mm256_andnot_ps(dummy_mask,fscal);
1476
1477             /* Calculate temporary vectorial force */
1478             tx               = _mm256_mul_ps(fscal,dx10);
1479             ty               = _mm256_mul_ps(fscal,dy10);
1480             tz               = _mm256_mul_ps(fscal,dz10);
1481
1482             /* Update vectorial force */
1483             fix1             = _mm256_add_ps(fix1,tx);
1484             fiy1             = _mm256_add_ps(fiy1,ty);
1485             fiz1             = _mm256_add_ps(fiz1,tz);
1486
1487             fjx0             = _mm256_add_ps(fjx0,tx);
1488             fjy0             = _mm256_add_ps(fjy0,ty);
1489             fjz0             = _mm256_add_ps(fjz0,tz);
1490
1491             /**************************
1492              * CALCULATE INTERACTIONS *
1493              **************************/
1494
1495             r20              = _mm256_mul_ps(rsq20,rinv20);
1496             r20              = _mm256_andnot_ps(dummy_mask,r20);
1497
1498             /* Compute parameters for interactions between i and j atoms */
1499             qq20             = _mm256_mul_ps(iq2,jq0);
1500
1501             /* EWALD ELECTROSTATICS */
1502             
1503             /* Analytical PME correction */
1504             zeta2            = _mm256_mul_ps(beta2,rsq20);
1505             rinv3            = _mm256_mul_ps(rinvsq20,rinv20);
1506             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
1507             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
1508             felec            = _mm256_mul_ps(qq20,felec);
1509             
1510             fscal            = felec;
1511
1512             fscal            = _mm256_andnot_ps(dummy_mask,fscal);
1513
1514             /* Calculate temporary vectorial force */
1515             tx               = _mm256_mul_ps(fscal,dx20);
1516             ty               = _mm256_mul_ps(fscal,dy20);
1517             tz               = _mm256_mul_ps(fscal,dz20);
1518
1519             /* Update vectorial force */
1520             fix2             = _mm256_add_ps(fix2,tx);
1521             fiy2             = _mm256_add_ps(fiy2,ty);
1522             fiz2             = _mm256_add_ps(fiz2,tz);
1523
1524             fjx0             = _mm256_add_ps(fjx0,tx);
1525             fjy0             = _mm256_add_ps(fjy0,ty);
1526             fjz0             = _mm256_add_ps(fjz0,tz);
1527
1528             /**************************
1529              * CALCULATE INTERACTIONS *
1530              **************************/
1531
1532             r30              = _mm256_mul_ps(rsq30,rinv30);
1533             r30              = _mm256_andnot_ps(dummy_mask,r30);
1534
1535             /* Compute parameters for interactions between i and j atoms */
1536             qq30             = _mm256_mul_ps(iq3,jq0);
1537
1538             /* EWALD ELECTROSTATICS */
1539             
1540             /* Analytical PME correction */
1541             zeta2            = _mm256_mul_ps(beta2,rsq30);
1542             rinv3            = _mm256_mul_ps(rinvsq30,rinv30);
1543             pmecorrF         = gmx_mm256_pmecorrF_ps(zeta2);
1544             felec            = _mm256_add_ps( _mm256_mul_ps(pmecorrF,beta3), rinv3);
1545             felec            = _mm256_mul_ps(qq30,felec);
1546             
1547             fscal            = felec;
1548
1549             fscal            = _mm256_andnot_ps(dummy_mask,fscal);
1550
1551             /* Calculate temporary vectorial force */
1552             tx               = _mm256_mul_ps(fscal,dx30);
1553             ty               = _mm256_mul_ps(fscal,dy30);
1554             tz               = _mm256_mul_ps(fscal,dz30);
1555
1556             /* Update vectorial force */
1557             fix3             = _mm256_add_ps(fix3,tx);
1558             fiy3             = _mm256_add_ps(fiy3,ty);
1559             fiz3             = _mm256_add_ps(fiz3,tz);
1560
1561             fjx0             = _mm256_add_ps(fjx0,tx);
1562             fjy0             = _mm256_add_ps(fjy0,ty);
1563             fjz0             = _mm256_add_ps(fjz0,tz);
1564
1565             fjptrA             = (jnrlistA>=0) ? f+j_coord_offsetA : scratch;
1566             fjptrB             = (jnrlistB>=0) ? f+j_coord_offsetB : scratch;
1567             fjptrC             = (jnrlistC>=0) ? f+j_coord_offsetC : scratch;
1568             fjptrD             = (jnrlistD>=0) ? f+j_coord_offsetD : scratch;
1569             fjptrE             = (jnrlistE>=0) ? f+j_coord_offsetE : scratch;
1570             fjptrF             = (jnrlistF>=0) ? f+j_coord_offsetF : scratch;
1571             fjptrG             = (jnrlistG>=0) ? f+j_coord_offsetG : scratch;
1572             fjptrH             = (jnrlistH>=0) ? f+j_coord_offsetH : scratch;
1573
1574             gmx_mm256_decrement_1rvec_8ptr_swizzle_ps(fjptrA,fjptrB,fjptrC,fjptrD,fjptrE,fjptrF,fjptrG,fjptrH,fjx0,fjy0,fjz0);
1575
1576             /* Inner loop uses 223 flops */
1577         }
1578
1579         /* End of innermost loop */
1580
1581         gmx_mm256_update_iforce_4atom_swizzle_ps(fix0,fiy0,fiz0,fix1,fiy1,fiz1,fix2,fiy2,fiz2,fix3,fiy3,fiz3,
1582                                                  f+i_coord_offset,fshift+i_shift_offset);
1583
1584         /* Increment number of inner iterations */
1585         inneriter                  += j_index_end - j_index_start;
1586
1587         /* Outer loop uses 24 flops */
1588     }
1589
1590     /* Increment number of outer iterations */
1591     outeriter        += nri;
1592
1593     /* Update outer/inner flops */
1594
1595     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_VDW_W4_F,outeriter*24 + inneriter*223);
1596 }