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