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