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