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