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