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