made errors during GPU detection non-fatal
[alexxy/gromacs.git] / src / gmxlib / nonbonded / nb_kernel_avx_128_fma_single / nb_kernel_ElecCSTab_VdwLJ_GeomW3P1_avx_128_fma_single.c
1 /*
2  * Note: this file was generated by the Gromacs avx_128_fma_single kernel generator.
3  *
4  *                This source code is part of
5  *
6  *                 G   R   O   M   A   C   S
7  *
8  * Copyright (c) 2001-2012, The GROMACS Development Team
9  *
10  * Gromacs is a library for molecular simulation and trajectory analysis,
11  * written by Erik Lindahl, David van der Spoel, Berk Hess, and others - for
12  * a full list of developers and information, check out http://www.gromacs.org
13  *
14  * This program is free software; you can redistribute it and/or modify it under
15  * the terms of the GNU Lesser General Public License as published by the Free
16  * Software Foundation; either version 2 of the License, or (at your option) any
17  * later version.
18  *
19  * To help fund GROMACS development, we humbly ask that you cite
20  * the papers people have written on it - you can find them on the website.
21  */
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <math.h>
27
28 #include "../nb_kernel.h"
29 #include "types/simple.h"
30 #include "vec.h"
31 #include "nrnb.h"
32
33 #include "gmx_math_x86_avx_128_fma_single.h"
34 #include "kernelutil_x86_avx_128_fma_single.h"
35
36 /*
37  * Gromacs nonbonded kernel:   nb_kernel_ElecCSTab_VdwLJ_GeomW3P1_VF_avx_128_fma_single
38  * Electrostatics interaction: CubicSplineTable
39  * VdW interaction:            LennardJones
40  * Geometry:                   Water3-Particle
41  * Calculate force/pot:        PotentialAndForce
42  */
43 void
44 nb_kernel_ElecCSTab_VdwLJ_GeomW3P1_VF_avx_128_fma_single
45                     (t_nblist * gmx_restrict                nlist,
46                      rvec * gmx_restrict                    xx,
47                      rvec * gmx_restrict                    ff,
48                      t_forcerec * gmx_restrict              fr,
49                      t_mdatoms * gmx_restrict               mdatoms,
50                      nb_kernel_data_t * gmx_restrict        kernel_data,
51                      t_nrnb * gmx_restrict                  nrnb)
52 {
53     /* Suffixes 0,1,2,3 refer to particle indices for waters in the inner or outer loop, or
54      * just 0 for non-waters.
55      * Suffixes A,B,C,D refer to j loop unrolling done with AVX_128, e.g. for the four different
56      * jnr indices corresponding to data put in the four positions in the SIMD register.
57      */
58     int              i_shift_offset,i_coord_offset,outeriter,inneriter;
59     int              j_index_start,j_index_end,jidx,nri,inr,ggid,iidx;
60     int              jnrA,jnrB,jnrC,jnrD;
61     int              jnrlistA,jnrlistB,jnrlistC,jnrlistD;
62     int              j_coord_offsetA,j_coord_offsetB,j_coord_offsetC,j_coord_offsetD;
63     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
64     real             rcutoff_scalar;
65     real             *shiftvec,*fshift,*x,*f;
66     real             *fjptrA,*fjptrB,*fjptrC,*fjptrD;
67     real             scratch[4*DIM];
68     __m128           fscal,rcutoff,rcutoff2,jidxall;
69     int              vdwioffset0;
70     __m128           ix0,iy0,iz0,fix0,fiy0,fiz0,iq0,isai0;
71     int              vdwioffset1;
72     __m128           ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
73     int              vdwioffset2;
74     __m128           ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
75     int              vdwjidx0A,vdwjidx0B,vdwjidx0C,vdwjidx0D;
76     __m128           jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
77     __m128           dx00,dy00,dz00,rsq00,rinv00,rinvsq00,r00,qq00,c6_00,c12_00;
78     __m128           dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10;
79     __m128           dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20;
80     __m128           velec,felec,velecsum,facel,crf,krf,krf2;
81     real             *charge;
82     int              nvdwtype;
83     __m128           rinvsix,rvdw,vvdw,vvdw6,vvdw12,fvdw,fvdw6,fvdw12,vvdwsum,sh_vdw_invrcut6;
84     int              *vdwtype;
85     real             *vdwparam;
86     __m128           one_sixth   = _mm_set1_ps(1.0/6.0);
87     __m128           one_twelfth = _mm_set1_ps(1.0/12.0);
88     __m128i          vfitab;
89     __m128i          ifour       = _mm_set1_epi32(4);
90     __m128           rt,vfeps,twovfeps,vftabscale,Y,F,G,H,Fp,VV,FF;
91     real             *vftab;
92     __m128           dummy_mask,cutoff_mask;
93     __m128           signbit = _mm_castsi128_ps( _mm_set1_epi32(0x80000000) );
94     __m128           one     = _mm_set1_ps(1.0);
95     __m128           two     = _mm_set1_ps(2.0);
96     x                = xx[0];
97     f                = ff[0];
98
99     nri              = nlist->nri;
100     iinr             = nlist->iinr;
101     jindex           = nlist->jindex;
102     jjnr             = nlist->jjnr;
103     shiftidx         = nlist->shift;
104     gid              = nlist->gid;
105     shiftvec         = fr->shift_vec[0];
106     fshift           = fr->fshift[0];
107     facel            = _mm_set1_ps(fr->epsfac);
108     charge           = mdatoms->chargeA;
109     nvdwtype         = fr->ntype;
110     vdwparam         = fr->nbfp;
111     vdwtype          = mdatoms->typeA;
112
113     vftab            = kernel_data->table_elec->data;
114     vftabscale       = _mm_set1_ps(kernel_data->table_elec->scale);
115
116     /* Setup water-specific parameters */
117     inr              = nlist->iinr[0];
118     iq0              = _mm_mul_ps(facel,_mm_set1_ps(charge[inr+0]));
119     iq1              = _mm_mul_ps(facel,_mm_set1_ps(charge[inr+1]));
120     iq2              = _mm_mul_ps(facel,_mm_set1_ps(charge[inr+2]));
121     vdwioffset0      = 2*nvdwtype*vdwtype[inr+0];
122
123     /* Avoid stupid compiler warnings */
124     jnrA = jnrB = jnrC = jnrD = 0;
125     j_coord_offsetA = 0;
126     j_coord_offsetB = 0;
127     j_coord_offsetC = 0;
128     j_coord_offsetD = 0;
129
130     outeriter        = 0;
131     inneriter        = 0;
132
133     for(iidx=0;iidx<4*DIM;iidx++)
134     {
135         scratch[iidx] = 0.0;
136     }
137
138     /* Start outer loop over neighborlists */
139     for(iidx=0; iidx<nri; iidx++)
140     {
141         /* Load shift vector for this list */
142         i_shift_offset   = DIM*shiftidx[iidx];
143
144         /* Load limits for loop over neighbors */
145         j_index_start    = jindex[iidx];
146         j_index_end      = jindex[iidx+1];
147
148         /* Get outer coordinate index */
149         inr              = iinr[iidx];
150         i_coord_offset   = DIM*inr;
151
152         /* Load i particle coords and add shift vector */
153         gmx_mm_load_shift_and_3rvec_broadcast_ps(shiftvec+i_shift_offset,x+i_coord_offset,
154                                                  &ix0,&iy0,&iz0,&ix1,&iy1,&iz1,&ix2,&iy2,&iz2);
155
156         fix0             = _mm_setzero_ps();
157         fiy0             = _mm_setzero_ps();
158         fiz0             = _mm_setzero_ps();
159         fix1             = _mm_setzero_ps();
160         fiy1             = _mm_setzero_ps();
161         fiz1             = _mm_setzero_ps();
162         fix2             = _mm_setzero_ps();
163         fiy2             = _mm_setzero_ps();
164         fiz2             = _mm_setzero_ps();
165
166         /* Reset potential sums */
167         velecsum         = _mm_setzero_ps();
168         vvdwsum          = _mm_setzero_ps();
169
170         /* Start inner kernel loop */
171         for(jidx=j_index_start; jidx<j_index_end && jjnr[jidx+3]>=0; jidx+=4)
172         {
173
174             /* Get j neighbor index, and coordinate index */
175             jnrA             = jjnr[jidx];
176             jnrB             = jjnr[jidx+1];
177             jnrC             = jjnr[jidx+2];
178             jnrD             = jjnr[jidx+3];
179             j_coord_offsetA  = DIM*jnrA;
180             j_coord_offsetB  = DIM*jnrB;
181             j_coord_offsetC  = DIM*jnrC;
182             j_coord_offsetD  = DIM*jnrD;
183
184             /* load j atom coordinates */
185             gmx_mm_load_1rvec_4ptr_swizzle_ps(x+j_coord_offsetA,x+j_coord_offsetB,
186                                               x+j_coord_offsetC,x+j_coord_offsetD,
187                                               &jx0,&jy0,&jz0);
188
189             /* Calculate displacement vector */
190             dx00             = _mm_sub_ps(ix0,jx0);
191             dy00             = _mm_sub_ps(iy0,jy0);
192             dz00             = _mm_sub_ps(iz0,jz0);
193             dx10             = _mm_sub_ps(ix1,jx0);
194             dy10             = _mm_sub_ps(iy1,jy0);
195             dz10             = _mm_sub_ps(iz1,jz0);
196             dx20             = _mm_sub_ps(ix2,jx0);
197             dy20             = _mm_sub_ps(iy2,jy0);
198             dz20             = _mm_sub_ps(iz2,jz0);
199
200             /* Calculate squared distance and things based on it */
201             rsq00            = gmx_mm_calc_rsq_ps(dx00,dy00,dz00);
202             rsq10            = gmx_mm_calc_rsq_ps(dx10,dy10,dz10);
203             rsq20            = gmx_mm_calc_rsq_ps(dx20,dy20,dz20);
204
205             rinv00           = gmx_mm_invsqrt_ps(rsq00);
206             rinv10           = gmx_mm_invsqrt_ps(rsq10);
207             rinv20           = gmx_mm_invsqrt_ps(rsq20);
208
209             rinvsq00         = _mm_mul_ps(rinv00,rinv00);
210
211             /* Load parameters for j particles */
212             jq0              = gmx_mm_load_4real_swizzle_ps(charge+jnrA+0,charge+jnrB+0,
213                                                               charge+jnrC+0,charge+jnrD+0);
214             vdwjidx0A        = 2*vdwtype[jnrA+0];
215             vdwjidx0B        = 2*vdwtype[jnrB+0];
216             vdwjidx0C        = 2*vdwtype[jnrC+0];
217             vdwjidx0D        = 2*vdwtype[jnrD+0];
218
219             fjx0             = _mm_setzero_ps();
220             fjy0             = _mm_setzero_ps();
221             fjz0             = _mm_setzero_ps();
222
223             /**************************
224              * CALCULATE INTERACTIONS *
225              **************************/
226
227             r00              = _mm_mul_ps(rsq00,rinv00);
228
229             /* Compute parameters for interactions between i and j atoms */
230             qq00             = _mm_mul_ps(iq0,jq0);
231             gmx_mm_load_4pair_swizzle_ps(vdwparam+vdwioffset0+vdwjidx0A,
232                                          vdwparam+vdwioffset0+vdwjidx0B,
233                                          vdwparam+vdwioffset0+vdwjidx0C,
234                                          vdwparam+vdwioffset0+vdwjidx0D,
235                                          &c6_00,&c12_00);
236
237             /* Calculate table index by multiplying r with table scale and truncate to integer */
238             rt               = _mm_mul_ps(r00,vftabscale);
239             vfitab           = _mm_cvttps_epi32(rt);
240 #ifdef __XOP__
241             vfeps            = _mm_frcz_ps(rt);
242 #else
243             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
244 #endif
245             twovfeps         = _mm_add_ps(vfeps,vfeps);
246             vfitab           = _mm_slli_epi32(vfitab,2);
247
248             /* CUBIC SPLINE TABLE ELECTROSTATICS */
249             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
250             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
251             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
252             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
253             _MM_TRANSPOSE4_PS(Y,F,G,H);
254             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
255             VV               = _mm_macc_ps(vfeps,Fp,Y);
256             velec            = _mm_mul_ps(qq00,VV);
257             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
258             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq00,FF),_mm_mul_ps(vftabscale,rinv00)));
259
260             /* LENNARD-JONES DISPERSION/REPULSION */
261
262             rinvsix          = _mm_mul_ps(_mm_mul_ps(rinvsq00,rinvsq00),rinvsq00);
263             vvdw6            = _mm_mul_ps(c6_00,rinvsix);
264             vvdw12           = _mm_mul_ps(c12_00,_mm_mul_ps(rinvsix,rinvsix));
265             vvdw             = _mm_msub_ps(vvdw12,one_twelfth,_mm_mul_ps(vvdw6,one_sixth));
266             fvdw             = _mm_mul_ps(_mm_sub_ps(vvdw12,vvdw6),rinvsq00);
267
268             /* Update potential sum for this i atom from the interaction with this j atom. */
269             velecsum         = _mm_add_ps(velecsum,velec);
270             vvdwsum          = _mm_add_ps(vvdwsum,vvdw);
271
272             fscal            = _mm_add_ps(felec,fvdw);
273
274              /* Update vectorial force */
275             fix0             = _mm_macc_ps(dx00,fscal,fix0);
276             fiy0             = _mm_macc_ps(dy00,fscal,fiy0);
277             fiz0             = _mm_macc_ps(dz00,fscal,fiz0);
278
279             fjx0             = _mm_macc_ps(dx00,fscal,fjx0);
280             fjy0             = _mm_macc_ps(dy00,fscal,fjy0);
281             fjz0             = _mm_macc_ps(dz00,fscal,fjz0);
282
283             /**************************
284              * CALCULATE INTERACTIONS *
285              **************************/
286
287             r10              = _mm_mul_ps(rsq10,rinv10);
288
289             /* Compute parameters for interactions between i and j atoms */
290             qq10             = _mm_mul_ps(iq1,jq0);
291
292             /* Calculate table index by multiplying r with table scale and truncate to integer */
293             rt               = _mm_mul_ps(r10,vftabscale);
294             vfitab           = _mm_cvttps_epi32(rt);
295 #ifdef __XOP__
296             vfeps            = _mm_frcz_ps(rt);
297 #else
298             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
299 #endif
300             twovfeps         = _mm_add_ps(vfeps,vfeps);
301             vfitab           = _mm_slli_epi32(vfitab,2);
302
303             /* CUBIC SPLINE TABLE ELECTROSTATICS */
304             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
305             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
306             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
307             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
308             _MM_TRANSPOSE4_PS(Y,F,G,H);
309             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
310             VV               = _mm_macc_ps(vfeps,Fp,Y);
311             velec            = _mm_mul_ps(qq10,VV);
312             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
313             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq10,FF),_mm_mul_ps(vftabscale,rinv10)));
314
315             /* Update potential sum for this i atom from the interaction with this j atom. */
316             velecsum         = _mm_add_ps(velecsum,velec);
317
318             fscal            = felec;
319
320              /* Update vectorial force */
321             fix1             = _mm_macc_ps(dx10,fscal,fix1);
322             fiy1             = _mm_macc_ps(dy10,fscal,fiy1);
323             fiz1             = _mm_macc_ps(dz10,fscal,fiz1);
324
325             fjx0             = _mm_macc_ps(dx10,fscal,fjx0);
326             fjy0             = _mm_macc_ps(dy10,fscal,fjy0);
327             fjz0             = _mm_macc_ps(dz10,fscal,fjz0);
328
329             /**************************
330              * CALCULATE INTERACTIONS *
331              **************************/
332
333             r20              = _mm_mul_ps(rsq20,rinv20);
334
335             /* Compute parameters for interactions between i and j atoms */
336             qq20             = _mm_mul_ps(iq2,jq0);
337
338             /* Calculate table index by multiplying r with table scale and truncate to integer */
339             rt               = _mm_mul_ps(r20,vftabscale);
340             vfitab           = _mm_cvttps_epi32(rt);
341 #ifdef __XOP__
342             vfeps            = _mm_frcz_ps(rt);
343 #else
344             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
345 #endif
346             twovfeps         = _mm_add_ps(vfeps,vfeps);
347             vfitab           = _mm_slli_epi32(vfitab,2);
348
349             /* CUBIC SPLINE TABLE ELECTROSTATICS */
350             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
351             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
352             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
353             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
354             _MM_TRANSPOSE4_PS(Y,F,G,H);
355             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
356             VV               = _mm_macc_ps(vfeps,Fp,Y);
357             velec            = _mm_mul_ps(qq20,VV);
358             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
359             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq20,FF),_mm_mul_ps(vftabscale,rinv20)));
360
361             /* Update potential sum for this i atom from the interaction with this j atom. */
362             velecsum         = _mm_add_ps(velecsum,velec);
363
364             fscal            = felec;
365
366              /* Update vectorial force */
367             fix2             = _mm_macc_ps(dx20,fscal,fix2);
368             fiy2             = _mm_macc_ps(dy20,fscal,fiy2);
369             fiz2             = _mm_macc_ps(dz20,fscal,fiz2);
370
371             fjx0             = _mm_macc_ps(dx20,fscal,fjx0);
372             fjy0             = _mm_macc_ps(dy20,fscal,fjy0);
373             fjz0             = _mm_macc_ps(dz20,fscal,fjz0);
374
375             fjptrA             = f+j_coord_offsetA;
376             fjptrB             = f+j_coord_offsetB;
377             fjptrC             = f+j_coord_offsetC;
378             fjptrD             = f+j_coord_offsetD;
379
380             gmx_mm_decrement_1rvec_4ptr_swizzle_ps(fjptrA,fjptrB,fjptrC,fjptrD,fjx0,fjy0,fjz0);
381
382             /* Inner loop uses 151 flops */
383         }
384
385         if(jidx<j_index_end)
386         {
387
388             /* Get j neighbor index, and coordinate index */
389             jnrlistA         = jjnr[jidx];
390             jnrlistB         = jjnr[jidx+1];
391             jnrlistC         = jjnr[jidx+2];
392             jnrlistD         = jjnr[jidx+3];
393             /* Sign of each element will be negative for non-real atoms.
394              * This mask will be 0xFFFFFFFF for dummy entries and 0x0 for real ones,
395              * so use it as val = _mm_andnot_ps(mask,val) to clear dummy entries.
396              */
397             dummy_mask = gmx_mm_castsi128_ps(_mm_cmplt_epi32(_mm_loadu_si128((const __m128i *)(jjnr+jidx)),_mm_setzero_si128()));
398             jnrA       = (jnrlistA>=0) ? jnrlistA : 0;
399             jnrB       = (jnrlistB>=0) ? jnrlistB : 0;
400             jnrC       = (jnrlistC>=0) ? jnrlistC : 0;
401             jnrD       = (jnrlistD>=0) ? jnrlistD : 0;
402             j_coord_offsetA  = DIM*jnrA;
403             j_coord_offsetB  = DIM*jnrB;
404             j_coord_offsetC  = DIM*jnrC;
405             j_coord_offsetD  = DIM*jnrD;
406
407             /* load j atom coordinates */
408             gmx_mm_load_1rvec_4ptr_swizzle_ps(x+j_coord_offsetA,x+j_coord_offsetB,
409                                               x+j_coord_offsetC,x+j_coord_offsetD,
410                                               &jx0,&jy0,&jz0);
411
412             /* Calculate displacement vector */
413             dx00             = _mm_sub_ps(ix0,jx0);
414             dy00             = _mm_sub_ps(iy0,jy0);
415             dz00             = _mm_sub_ps(iz0,jz0);
416             dx10             = _mm_sub_ps(ix1,jx0);
417             dy10             = _mm_sub_ps(iy1,jy0);
418             dz10             = _mm_sub_ps(iz1,jz0);
419             dx20             = _mm_sub_ps(ix2,jx0);
420             dy20             = _mm_sub_ps(iy2,jy0);
421             dz20             = _mm_sub_ps(iz2,jz0);
422
423             /* Calculate squared distance and things based on it */
424             rsq00            = gmx_mm_calc_rsq_ps(dx00,dy00,dz00);
425             rsq10            = gmx_mm_calc_rsq_ps(dx10,dy10,dz10);
426             rsq20            = gmx_mm_calc_rsq_ps(dx20,dy20,dz20);
427
428             rinv00           = gmx_mm_invsqrt_ps(rsq00);
429             rinv10           = gmx_mm_invsqrt_ps(rsq10);
430             rinv20           = gmx_mm_invsqrt_ps(rsq20);
431
432             rinvsq00         = _mm_mul_ps(rinv00,rinv00);
433
434             /* Load parameters for j particles */
435             jq0              = gmx_mm_load_4real_swizzle_ps(charge+jnrA+0,charge+jnrB+0,
436                                                               charge+jnrC+0,charge+jnrD+0);
437             vdwjidx0A        = 2*vdwtype[jnrA+0];
438             vdwjidx0B        = 2*vdwtype[jnrB+0];
439             vdwjidx0C        = 2*vdwtype[jnrC+0];
440             vdwjidx0D        = 2*vdwtype[jnrD+0];
441
442             fjx0             = _mm_setzero_ps();
443             fjy0             = _mm_setzero_ps();
444             fjz0             = _mm_setzero_ps();
445
446             /**************************
447              * CALCULATE INTERACTIONS *
448              **************************/
449
450             r00              = _mm_mul_ps(rsq00,rinv00);
451             r00              = _mm_andnot_ps(dummy_mask,r00);
452
453             /* Compute parameters for interactions between i and j atoms */
454             qq00             = _mm_mul_ps(iq0,jq0);
455             gmx_mm_load_4pair_swizzle_ps(vdwparam+vdwioffset0+vdwjidx0A,
456                                          vdwparam+vdwioffset0+vdwjidx0B,
457                                          vdwparam+vdwioffset0+vdwjidx0C,
458                                          vdwparam+vdwioffset0+vdwjidx0D,
459                                          &c6_00,&c12_00);
460
461             /* Calculate table index by multiplying r with table scale and truncate to integer */
462             rt               = _mm_mul_ps(r00,vftabscale);
463             vfitab           = _mm_cvttps_epi32(rt);
464 #ifdef __XOP__
465             vfeps            = _mm_frcz_ps(rt);
466 #else
467             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
468 #endif
469             twovfeps         = _mm_add_ps(vfeps,vfeps);
470             vfitab           = _mm_slli_epi32(vfitab,2);
471
472             /* CUBIC SPLINE TABLE ELECTROSTATICS */
473             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
474             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
475             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
476             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
477             _MM_TRANSPOSE4_PS(Y,F,G,H);
478             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
479             VV               = _mm_macc_ps(vfeps,Fp,Y);
480             velec            = _mm_mul_ps(qq00,VV);
481             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
482             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq00,FF),_mm_mul_ps(vftabscale,rinv00)));
483
484             /* LENNARD-JONES DISPERSION/REPULSION */
485
486             rinvsix          = _mm_mul_ps(_mm_mul_ps(rinvsq00,rinvsq00),rinvsq00);
487             vvdw6            = _mm_mul_ps(c6_00,rinvsix);
488             vvdw12           = _mm_mul_ps(c12_00,_mm_mul_ps(rinvsix,rinvsix));
489             vvdw             = _mm_msub_ps(vvdw12,one_twelfth,_mm_mul_ps(vvdw6,one_sixth));
490             fvdw             = _mm_mul_ps(_mm_sub_ps(vvdw12,vvdw6),rinvsq00);
491
492             /* Update potential sum for this i atom from the interaction with this j atom. */
493             velec            = _mm_andnot_ps(dummy_mask,velec);
494             velecsum         = _mm_add_ps(velecsum,velec);
495             vvdw             = _mm_andnot_ps(dummy_mask,vvdw);
496             vvdwsum          = _mm_add_ps(vvdwsum,vvdw);
497
498             fscal            = _mm_add_ps(felec,fvdw);
499
500             fscal            = _mm_andnot_ps(dummy_mask,fscal);
501
502              /* Update vectorial force */
503             fix0             = _mm_macc_ps(dx00,fscal,fix0);
504             fiy0             = _mm_macc_ps(dy00,fscal,fiy0);
505             fiz0             = _mm_macc_ps(dz00,fscal,fiz0);
506
507             fjx0             = _mm_macc_ps(dx00,fscal,fjx0);
508             fjy0             = _mm_macc_ps(dy00,fscal,fjy0);
509             fjz0             = _mm_macc_ps(dz00,fscal,fjz0);
510
511             /**************************
512              * CALCULATE INTERACTIONS *
513              **************************/
514
515             r10              = _mm_mul_ps(rsq10,rinv10);
516             r10              = _mm_andnot_ps(dummy_mask,r10);
517
518             /* Compute parameters for interactions between i and j atoms */
519             qq10             = _mm_mul_ps(iq1,jq0);
520
521             /* Calculate table index by multiplying r with table scale and truncate to integer */
522             rt               = _mm_mul_ps(r10,vftabscale);
523             vfitab           = _mm_cvttps_epi32(rt);
524 #ifdef __XOP__
525             vfeps            = _mm_frcz_ps(rt);
526 #else
527             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
528 #endif
529             twovfeps         = _mm_add_ps(vfeps,vfeps);
530             vfitab           = _mm_slli_epi32(vfitab,2);
531
532             /* CUBIC SPLINE TABLE ELECTROSTATICS */
533             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
534             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
535             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
536             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
537             _MM_TRANSPOSE4_PS(Y,F,G,H);
538             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
539             VV               = _mm_macc_ps(vfeps,Fp,Y);
540             velec            = _mm_mul_ps(qq10,VV);
541             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
542             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq10,FF),_mm_mul_ps(vftabscale,rinv10)));
543
544             /* Update potential sum for this i atom from the interaction with this j atom. */
545             velec            = _mm_andnot_ps(dummy_mask,velec);
546             velecsum         = _mm_add_ps(velecsum,velec);
547
548             fscal            = felec;
549
550             fscal            = _mm_andnot_ps(dummy_mask,fscal);
551
552              /* Update vectorial force */
553             fix1             = _mm_macc_ps(dx10,fscal,fix1);
554             fiy1             = _mm_macc_ps(dy10,fscal,fiy1);
555             fiz1             = _mm_macc_ps(dz10,fscal,fiz1);
556
557             fjx0             = _mm_macc_ps(dx10,fscal,fjx0);
558             fjy0             = _mm_macc_ps(dy10,fscal,fjy0);
559             fjz0             = _mm_macc_ps(dz10,fscal,fjz0);
560
561             /**************************
562              * CALCULATE INTERACTIONS *
563              **************************/
564
565             r20              = _mm_mul_ps(rsq20,rinv20);
566             r20              = _mm_andnot_ps(dummy_mask,r20);
567
568             /* Compute parameters for interactions between i and j atoms */
569             qq20             = _mm_mul_ps(iq2,jq0);
570
571             /* Calculate table index by multiplying r with table scale and truncate to integer */
572             rt               = _mm_mul_ps(r20,vftabscale);
573             vfitab           = _mm_cvttps_epi32(rt);
574 #ifdef __XOP__
575             vfeps            = _mm_frcz_ps(rt);
576 #else
577             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
578 #endif
579             twovfeps         = _mm_add_ps(vfeps,vfeps);
580             vfitab           = _mm_slli_epi32(vfitab,2);
581
582             /* CUBIC SPLINE TABLE ELECTROSTATICS */
583             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
584             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
585             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
586             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
587             _MM_TRANSPOSE4_PS(Y,F,G,H);
588             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
589             VV               = _mm_macc_ps(vfeps,Fp,Y);
590             velec            = _mm_mul_ps(qq20,VV);
591             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
592             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq20,FF),_mm_mul_ps(vftabscale,rinv20)));
593
594             /* Update potential sum for this i atom from the interaction with this j atom. */
595             velec            = _mm_andnot_ps(dummy_mask,velec);
596             velecsum         = _mm_add_ps(velecsum,velec);
597
598             fscal            = felec;
599
600             fscal            = _mm_andnot_ps(dummy_mask,fscal);
601
602              /* Update vectorial force */
603             fix2             = _mm_macc_ps(dx20,fscal,fix2);
604             fiy2             = _mm_macc_ps(dy20,fscal,fiy2);
605             fiz2             = _mm_macc_ps(dz20,fscal,fiz2);
606
607             fjx0             = _mm_macc_ps(dx20,fscal,fjx0);
608             fjy0             = _mm_macc_ps(dy20,fscal,fjy0);
609             fjz0             = _mm_macc_ps(dz20,fscal,fjz0);
610
611             fjptrA             = (jnrlistA>=0) ? f+j_coord_offsetA : scratch;
612             fjptrB             = (jnrlistB>=0) ? f+j_coord_offsetB : scratch;
613             fjptrC             = (jnrlistC>=0) ? f+j_coord_offsetC : scratch;
614             fjptrD             = (jnrlistD>=0) ? f+j_coord_offsetD : scratch;
615
616             gmx_mm_decrement_1rvec_4ptr_swizzle_ps(fjptrA,fjptrB,fjptrC,fjptrD,fjx0,fjy0,fjz0);
617
618             /* Inner loop uses 154 flops */
619         }
620
621         /* End of innermost loop */
622
623         gmx_mm_update_iforce_3atom_swizzle_ps(fix0,fiy0,fiz0,fix1,fiy1,fiz1,fix2,fiy2,fiz2,
624                                               f+i_coord_offset,fshift+i_shift_offset);
625
626         ggid                        = gid[iidx];
627         /* Update potential energies */
628         gmx_mm_update_1pot_ps(velecsum,kernel_data->energygrp_elec+ggid);
629         gmx_mm_update_1pot_ps(vvdwsum,kernel_data->energygrp_vdw+ggid);
630
631         /* Increment number of inner iterations */
632         inneriter                  += j_index_end - j_index_start;
633
634         /* Outer loop uses 20 flops */
635     }
636
637     /* Increment number of outer iterations */
638     outeriter        += nri;
639
640     /* Update outer/inner flops */
641
642     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_VDW_W3_VF,outeriter*20 + inneriter*154);
643 }
644 /*
645  * Gromacs nonbonded kernel:   nb_kernel_ElecCSTab_VdwLJ_GeomW3P1_F_avx_128_fma_single
646  * Electrostatics interaction: CubicSplineTable
647  * VdW interaction:            LennardJones
648  * Geometry:                   Water3-Particle
649  * Calculate force/pot:        Force
650  */
651 void
652 nb_kernel_ElecCSTab_VdwLJ_GeomW3P1_F_avx_128_fma_single
653                     (t_nblist * gmx_restrict                nlist,
654                      rvec * gmx_restrict                    xx,
655                      rvec * gmx_restrict                    ff,
656                      t_forcerec * gmx_restrict              fr,
657                      t_mdatoms * gmx_restrict               mdatoms,
658                      nb_kernel_data_t * gmx_restrict        kernel_data,
659                      t_nrnb * gmx_restrict                  nrnb)
660 {
661     /* Suffixes 0,1,2,3 refer to particle indices for waters in the inner or outer loop, or
662      * just 0 for non-waters.
663      * Suffixes A,B,C,D refer to j loop unrolling done with AVX_128, e.g. for the four different
664      * jnr indices corresponding to data put in the four positions in the SIMD register.
665      */
666     int              i_shift_offset,i_coord_offset,outeriter,inneriter;
667     int              j_index_start,j_index_end,jidx,nri,inr,ggid,iidx;
668     int              jnrA,jnrB,jnrC,jnrD;
669     int              jnrlistA,jnrlistB,jnrlistC,jnrlistD;
670     int              j_coord_offsetA,j_coord_offsetB,j_coord_offsetC,j_coord_offsetD;
671     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
672     real             rcutoff_scalar;
673     real             *shiftvec,*fshift,*x,*f;
674     real             *fjptrA,*fjptrB,*fjptrC,*fjptrD;
675     real             scratch[4*DIM];
676     __m128           fscal,rcutoff,rcutoff2,jidxall;
677     int              vdwioffset0;
678     __m128           ix0,iy0,iz0,fix0,fiy0,fiz0,iq0,isai0;
679     int              vdwioffset1;
680     __m128           ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
681     int              vdwioffset2;
682     __m128           ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
683     int              vdwjidx0A,vdwjidx0B,vdwjidx0C,vdwjidx0D;
684     __m128           jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
685     __m128           dx00,dy00,dz00,rsq00,rinv00,rinvsq00,r00,qq00,c6_00,c12_00;
686     __m128           dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10;
687     __m128           dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20;
688     __m128           velec,felec,velecsum,facel,crf,krf,krf2;
689     real             *charge;
690     int              nvdwtype;
691     __m128           rinvsix,rvdw,vvdw,vvdw6,vvdw12,fvdw,fvdw6,fvdw12,vvdwsum,sh_vdw_invrcut6;
692     int              *vdwtype;
693     real             *vdwparam;
694     __m128           one_sixth   = _mm_set1_ps(1.0/6.0);
695     __m128           one_twelfth = _mm_set1_ps(1.0/12.0);
696     __m128i          vfitab;
697     __m128i          ifour       = _mm_set1_epi32(4);
698     __m128           rt,vfeps,twovfeps,vftabscale,Y,F,G,H,Fp,VV,FF;
699     real             *vftab;
700     __m128           dummy_mask,cutoff_mask;
701     __m128           signbit = _mm_castsi128_ps( _mm_set1_epi32(0x80000000) );
702     __m128           one     = _mm_set1_ps(1.0);
703     __m128           two     = _mm_set1_ps(2.0);
704     x                = xx[0];
705     f                = ff[0];
706
707     nri              = nlist->nri;
708     iinr             = nlist->iinr;
709     jindex           = nlist->jindex;
710     jjnr             = nlist->jjnr;
711     shiftidx         = nlist->shift;
712     gid              = nlist->gid;
713     shiftvec         = fr->shift_vec[0];
714     fshift           = fr->fshift[0];
715     facel            = _mm_set1_ps(fr->epsfac);
716     charge           = mdatoms->chargeA;
717     nvdwtype         = fr->ntype;
718     vdwparam         = fr->nbfp;
719     vdwtype          = mdatoms->typeA;
720
721     vftab            = kernel_data->table_elec->data;
722     vftabscale       = _mm_set1_ps(kernel_data->table_elec->scale);
723
724     /* Setup water-specific parameters */
725     inr              = nlist->iinr[0];
726     iq0              = _mm_mul_ps(facel,_mm_set1_ps(charge[inr+0]));
727     iq1              = _mm_mul_ps(facel,_mm_set1_ps(charge[inr+1]));
728     iq2              = _mm_mul_ps(facel,_mm_set1_ps(charge[inr+2]));
729     vdwioffset0      = 2*nvdwtype*vdwtype[inr+0];
730
731     /* Avoid stupid compiler warnings */
732     jnrA = jnrB = jnrC = jnrD = 0;
733     j_coord_offsetA = 0;
734     j_coord_offsetB = 0;
735     j_coord_offsetC = 0;
736     j_coord_offsetD = 0;
737
738     outeriter        = 0;
739     inneriter        = 0;
740
741     for(iidx=0;iidx<4*DIM;iidx++)
742     {
743         scratch[iidx] = 0.0;
744     }
745
746     /* Start outer loop over neighborlists */
747     for(iidx=0; iidx<nri; iidx++)
748     {
749         /* Load shift vector for this list */
750         i_shift_offset   = DIM*shiftidx[iidx];
751
752         /* Load limits for loop over neighbors */
753         j_index_start    = jindex[iidx];
754         j_index_end      = jindex[iidx+1];
755
756         /* Get outer coordinate index */
757         inr              = iinr[iidx];
758         i_coord_offset   = DIM*inr;
759
760         /* Load i particle coords and add shift vector */
761         gmx_mm_load_shift_and_3rvec_broadcast_ps(shiftvec+i_shift_offset,x+i_coord_offset,
762                                                  &ix0,&iy0,&iz0,&ix1,&iy1,&iz1,&ix2,&iy2,&iz2);
763
764         fix0             = _mm_setzero_ps();
765         fiy0             = _mm_setzero_ps();
766         fiz0             = _mm_setzero_ps();
767         fix1             = _mm_setzero_ps();
768         fiy1             = _mm_setzero_ps();
769         fiz1             = _mm_setzero_ps();
770         fix2             = _mm_setzero_ps();
771         fiy2             = _mm_setzero_ps();
772         fiz2             = _mm_setzero_ps();
773
774         /* Start inner kernel loop */
775         for(jidx=j_index_start; jidx<j_index_end && jjnr[jidx+3]>=0; jidx+=4)
776         {
777
778             /* Get j neighbor index, and coordinate index */
779             jnrA             = jjnr[jidx];
780             jnrB             = jjnr[jidx+1];
781             jnrC             = jjnr[jidx+2];
782             jnrD             = jjnr[jidx+3];
783             j_coord_offsetA  = DIM*jnrA;
784             j_coord_offsetB  = DIM*jnrB;
785             j_coord_offsetC  = DIM*jnrC;
786             j_coord_offsetD  = DIM*jnrD;
787
788             /* load j atom coordinates */
789             gmx_mm_load_1rvec_4ptr_swizzle_ps(x+j_coord_offsetA,x+j_coord_offsetB,
790                                               x+j_coord_offsetC,x+j_coord_offsetD,
791                                               &jx0,&jy0,&jz0);
792
793             /* Calculate displacement vector */
794             dx00             = _mm_sub_ps(ix0,jx0);
795             dy00             = _mm_sub_ps(iy0,jy0);
796             dz00             = _mm_sub_ps(iz0,jz0);
797             dx10             = _mm_sub_ps(ix1,jx0);
798             dy10             = _mm_sub_ps(iy1,jy0);
799             dz10             = _mm_sub_ps(iz1,jz0);
800             dx20             = _mm_sub_ps(ix2,jx0);
801             dy20             = _mm_sub_ps(iy2,jy0);
802             dz20             = _mm_sub_ps(iz2,jz0);
803
804             /* Calculate squared distance and things based on it */
805             rsq00            = gmx_mm_calc_rsq_ps(dx00,dy00,dz00);
806             rsq10            = gmx_mm_calc_rsq_ps(dx10,dy10,dz10);
807             rsq20            = gmx_mm_calc_rsq_ps(dx20,dy20,dz20);
808
809             rinv00           = gmx_mm_invsqrt_ps(rsq00);
810             rinv10           = gmx_mm_invsqrt_ps(rsq10);
811             rinv20           = gmx_mm_invsqrt_ps(rsq20);
812
813             rinvsq00         = _mm_mul_ps(rinv00,rinv00);
814
815             /* Load parameters for j particles */
816             jq0              = gmx_mm_load_4real_swizzle_ps(charge+jnrA+0,charge+jnrB+0,
817                                                               charge+jnrC+0,charge+jnrD+0);
818             vdwjidx0A        = 2*vdwtype[jnrA+0];
819             vdwjidx0B        = 2*vdwtype[jnrB+0];
820             vdwjidx0C        = 2*vdwtype[jnrC+0];
821             vdwjidx0D        = 2*vdwtype[jnrD+0];
822
823             fjx0             = _mm_setzero_ps();
824             fjy0             = _mm_setzero_ps();
825             fjz0             = _mm_setzero_ps();
826
827             /**************************
828              * CALCULATE INTERACTIONS *
829              **************************/
830
831             r00              = _mm_mul_ps(rsq00,rinv00);
832
833             /* Compute parameters for interactions between i and j atoms */
834             qq00             = _mm_mul_ps(iq0,jq0);
835             gmx_mm_load_4pair_swizzle_ps(vdwparam+vdwioffset0+vdwjidx0A,
836                                          vdwparam+vdwioffset0+vdwjidx0B,
837                                          vdwparam+vdwioffset0+vdwjidx0C,
838                                          vdwparam+vdwioffset0+vdwjidx0D,
839                                          &c6_00,&c12_00);
840
841             /* Calculate table index by multiplying r with table scale and truncate to integer */
842             rt               = _mm_mul_ps(r00,vftabscale);
843             vfitab           = _mm_cvttps_epi32(rt);
844 #ifdef __XOP__
845             vfeps            = _mm_frcz_ps(rt);
846 #else
847             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
848 #endif
849             twovfeps         = _mm_add_ps(vfeps,vfeps);
850             vfitab           = _mm_slli_epi32(vfitab,2);
851
852             /* CUBIC SPLINE TABLE ELECTROSTATICS */
853             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
854             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
855             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
856             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
857             _MM_TRANSPOSE4_PS(Y,F,G,H);
858             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
859             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
860             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq00,FF),_mm_mul_ps(vftabscale,rinv00)));
861
862             /* LENNARD-JONES DISPERSION/REPULSION */
863
864             rinvsix          = _mm_mul_ps(_mm_mul_ps(rinvsq00,rinvsq00),rinvsq00);
865             fvdw             = _mm_mul_ps(_mm_msub_ps(c12_00,rinvsix,c6_00),_mm_mul_ps(rinvsix,rinvsq00));
866
867             fscal            = _mm_add_ps(felec,fvdw);
868
869              /* Update vectorial force */
870             fix0             = _mm_macc_ps(dx00,fscal,fix0);
871             fiy0             = _mm_macc_ps(dy00,fscal,fiy0);
872             fiz0             = _mm_macc_ps(dz00,fscal,fiz0);
873
874             fjx0             = _mm_macc_ps(dx00,fscal,fjx0);
875             fjy0             = _mm_macc_ps(dy00,fscal,fjy0);
876             fjz0             = _mm_macc_ps(dz00,fscal,fjz0);
877
878             /**************************
879              * CALCULATE INTERACTIONS *
880              **************************/
881
882             r10              = _mm_mul_ps(rsq10,rinv10);
883
884             /* Compute parameters for interactions between i and j atoms */
885             qq10             = _mm_mul_ps(iq1,jq0);
886
887             /* Calculate table index by multiplying r with table scale and truncate to integer */
888             rt               = _mm_mul_ps(r10,vftabscale);
889             vfitab           = _mm_cvttps_epi32(rt);
890 #ifdef __XOP__
891             vfeps            = _mm_frcz_ps(rt);
892 #else
893             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
894 #endif
895             twovfeps         = _mm_add_ps(vfeps,vfeps);
896             vfitab           = _mm_slli_epi32(vfitab,2);
897
898             /* CUBIC SPLINE TABLE ELECTROSTATICS */
899             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
900             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
901             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
902             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
903             _MM_TRANSPOSE4_PS(Y,F,G,H);
904             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
905             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
906             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq10,FF),_mm_mul_ps(vftabscale,rinv10)));
907
908             fscal            = felec;
909
910              /* Update vectorial force */
911             fix1             = _mm_macc_ps(dx10,fscal,fix1);
912             fiy1             = _mm_macc_ps(dy10,fscal,fiy1);
913             fiz1             = _mm_macc_ps(dz10,fscal,fiz1);
914
915             fjx0             = _mm_macc_ps(dx10,fscal,fjx0);
916             fjy0             = _mm_macc_ps(dy10,fscal,fjy0);
917             fjz0             = _mm_macc_ps(dz10,fscal,fjz0);
918
919             /**************************
920              * CALCULATE INTERACTIONS *
921              **************************/
922
923             r20              = _mm_mul_ps(rsq20,rinv20);
924
925             /* Compute parameters for interactions between i and j atoms */
926             qq20             = _mm_mul_ps(iq2,jq0);
927
928             /* Calculate table index by multiplying r with table scale and truncate to integer */
929             rt               = _mm_mul_ps(r20,vftabscale);
930             vfitab           = _mm_cvttps_epi32(rt);
931 #ifdef __XOP__
932             vfeps            = _mm_frcz_ps(rt);
933 #else
934             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
935 #endif
936             twovfeps         = _mm_add_ps(vfeps,vfeps);
937             vfitab           = _mm_slli_epi32(vfitab,2);
938
939             /* CUBIC SPLINE TABLE ELECTROSTATICS */
940             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
941             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
942             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
943             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
944             _MM_TRANSPOSE4_PS(Y,F,G,H);
945             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
946             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
947             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq20,FF),_mm_mul_ps(vftabscale,rinv20)));
948
949             fscal            = felec;
950
951              /* Update vectorial force */
952             fix2             = _mm_macc_ps(dx20,fscal,fix2);
953             fiy2             = _mm_macc_ps(dy20,fscal,fiy2);
954             fiz2             = _mm_macc_ps(dz20,fscal,fiz2);
955
956             fjx0             = _mm_macc_ps(dx20,fscal,fjx0);
957             fjy0             = _mm_macc_ps(dy20,fscal,fjy0);
958             fjz0             = _mm_macc_ps(dz20,fscal,fjz0);
959
960             fjptrA             = f+j_coord_offsetA;
961             fjptrB             = f+j_coord_offsetB;
962             fjptrC             = f+j_coord_offsetC;
963             fjptrD             = f+j_coord_offsetD;
964
965             gmx_mm_decrement_1rvec_4ptr_swizzle_ps(fjptrA,fjptrB,fjptrC,fjptrD,fjx0,fjy0,fjz0);
966
967             /* Inner loop uses 134 flops */
968         }
969
970         if(jidx<j_index_end)
971         {
972
973             /* Get j neighbor index, and coordinate index */
974             jnrlistA         = jjnr[jidx];
975             jnrlistB         = jjnr[jidx+1];
976             jnrlistC         = jjnr[jidx+2];
977             jnrlistD         = jjnr[jidx+3];
978             /* Sign of each element will be negative for non-real atoms.
979              * This mask will be 0xFFFFFFFF for dummy entries and 0x0 for real ones,
980              * so use it as val = _mm_andnot_ps(mask,val) to clear dummy entries.
981              */
982             dummy_mask = gmx_mm_castsi128_ps(_mm_cmplt_epi32(_mm_loadu_si128((const __m128i *)(jjnr+jidx)),_mm_setzero_si128()));
983             jnrA       = (jnrlistA>=0) ? jnrlistA : 0;
984             jnrB       = (jnrlistB>=0) ? jnrlistB : 0;
985             jnrC       = (jnrlistC>=0) ? jnrlistC : 0;
986             jnrD       = (jnrlistD>=0) ? jnrlistD : 0;
987             j_coord_offsetA  = DIM*jnrA;
988             j_coord_offsetB  = DIM*jnrB;
989             j_coord_offsetC  = DIM*jnrC;
990             j_coord_offsetD  = DIM*jnrD;
991
992             /* load j atom coordinates */
993             gmx_mm_load_1rvec_4ptr_swizzle_ps(x+j_coord_offsetA,x+j_coord_offsetB,
994                                               x+j_coord_offsetC,x+j_coord_offsetD,
995                                               &jx0,&jy0,&jz0);
996
997             /* Calculate displacement vector */
998             dx00             = _mm_sub_ps(ix0,jx0);
999             dy00             = _mm_sub_ps(iy0,jy0);
1000             dz00             = _mm_sub_ps(iz0,jz0);
1001             dx10             = _mm_sub_ps(ix1,jx0);
1002             dy10             = _mm_sub_ps(iy1,jy0);
1003             dz10             = _mm_sub_ps(iz1,jz0);
1004             dx20             = _mm_sub_ps(ix2,jx0);
1005             dy20             = _mm_sub_ps(iy2,jy0);
1006             dz20             = _mm_sub_ps(iz2,jz0);
1007
1008             /* Calculate squared distance and things based on it */
1009             rsq00            = gmx_mm_calc_rsq_ps(dx00,dy00,dz00);
1010             rsq10            = gmx_mm_calc_rsq_ps(dx10,dy10,dz10);
1011             rsq20            = gmx_mm_calc_rsq_ps(dx20,dy20,dz20);
1012
1013             rinv00           = gmx_mm_invsqrt_ps(rsq00);
1014             rinv10           = gmx_mm_invsqrt_ps(rsq10);
1015             rinv20           = gmx_mm_invsqrt_ps(rsq20);
1016
1017             rinvsq00         = _mm_mul_ps(rinv00,rinv00);
1018
1019             /* Load parameters for j particles */
1020             jq0              = gmx_mm_load_4real_swizzle_ps(charge+jnrA+0,charge+jnrB+0,
1021                                                               charge+jnrC+0,charge+jnrD+0);
1022             vdwjidx0A        = 2*vdwtype[jnrA+0];
1023             vdwjidx0B        = 2*vdwtype[jnrB+0];
1024             vdwjidx0C        = 2*vdwtype[jnrC+0];
1025             vdwjidx0D        = 2*vdwtype[jnrD+0];
1026
1027             fjx0             = _mm_setzero_ps();
1028             fjy0             = _mm_setzero_ps();
1029             fjz0             = _mm_setzero_ps();
1030
1031             /**************************
1032              * CALCULATE INTERACTIONS *
1033              **************************/
1034
1035             r00              = _mm_mul_ps(rsq00,rinv00);
1036             r00              = _mm_andnot_ps(dummy_mask,r00);
1037
1038             /* Compute parameters for interactions between i and j atoms */
1039             qq00             = _mm_mul_ps(iq0,jq0);
1040             gmx_mm_load_4pair_swizzle_ps(vdwparam+vdwioffset0+vdwjidx0A,
1041                                          vdwparam+vdwioffset0+vdwjidx0B,
1042                                          vdwparam+vdwioffset0+vdwjidx0C,
1043                                          vdwparam+vdwioffset0+vdwjidx0D,
1044                                          &c6_00,&c12_00);
1045
1046             /* Calculate table index by multiplying r with table scale and truncate to integer */
1047             rt               = _mm_mul_ps(r00,vftabscale);
1048             vfitab           = _mm_cvttps_epi32(rt);
1049 #ifdef __XOP__
1050             vfeps            = _mm_frcz_ps(rt);
1051 #else
1052             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
1053 #endif
1054             twovfeps         = _mm_add_ps(vfeps,vfeps);
1055             vfitab           = _mm_slli_epi32(vfitab,2);
1056
1057             /* CUBIC SPLINE TABLE ELECTROSTATICS */
1058             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
1059             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
1060             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
1061             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
1062             _MM_TRANSPOSE4_PS(Y,F,G,H);
1063             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
1064             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
1065             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq00,FF),_mm_mul_ps(vftabscale,rinv00)));
1066
1067             /* LENNARD-JONES DISPERSION/REPULSION */
1068
1069             rinvsix          = _mm_mul_ps(_mm_mul_ps(rinvsq00,rinvsq00),rinvsq00);
1070             fvdw             = _mm_mul_ps(_mm_msub_ps(c12_00,rinvsix,c6_00),_mm_mul_ps(rinvsix,rinvsq00));
1071
1072             fscal            = _mm_add_ps(felec,fvdw);
1073
1074             fscal            = _mm_andnot_ps(dummy_mask,fscal);
1075
1076              /* Update vectorial force */
1077             fix0             = _mm_macc_ps(dx00,fscal,fix0);
1078             fiy0             = _mm_macc_ps(dy00,fscal,fiy0);
1079             fiz0             = _mm_macc_ps(dz00,fscal,fiz0);
1080
1081             fjx0             = _mm_macc_ps(dx00,fscal,fjx0);
1082             fjy0             = _mm_macc_ps(dy00,fscal,fjy0);
1083             fjz0             = _mm_macc_ps(dz00,fscal,fjz0);
1084
1085             /**************************
1086              * CALCULATE INTERACTIONS *
1087              **************************/
1088
1089             r10              = _mm_mul_ps(rsq10,rinv10);
1090             r10              = _mm_andnot_ps(dummy_mask,r10);
1091
1092             /* Compute parameters for interactions between i and j atoms */
1093             qq10             = _mm_mul_ps(iq1,jq0);
1094
1095             /* Calculate table index by multiplying r with table scale and truncate to integer */
1096             rt               = _mm_mul_ps(r10,vftabscale);
1097             vfitab           = _mm_cvttps_epi32(rt);
1098 #ifdef __XOP__
1099             vfeps            = _mm_frcz_ps(rt);
1100 #else
1101             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
1102 #endif
1103             twovfeps         = _mm_add_ps(vfeps,vfeps);
1104             vfitab           = _mm_slli_epi32(vfitab,2);
1105
1106             /* CUBIC SPLINE TABLE ELECTROSTATICS */
1107             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
1108             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
1109             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
1110             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
1111             _MM_TRANSPOSE4_PS(Y,F,G,H);
1112             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
1113             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
1114             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq10,FF),_mm_mul_ps(vftabscale,rinv10)));
1115
1116             fscal            = felec;
1117
1118             fscal            = _mm_andnot_ps(dummy_mask,fscal);
1119
1120              /* Update vectorial force */
1121             fix1             = _mm_macc_ps(dx10,fscal,fix1);
1122             fiy1             = _mm_macc_ps(dy10,fscal,fiy1);
1123             fiz1             = _mm_macc_ps(dz10,fscal,fiz1);
1124
1125             fjx0             = _mm_macc_ps(dx10,fscal,fjx0);
1126             fjy0             = _mm_macc_ps(dy10,fscal,fjy0);
1127             fjz0             = _mm_macc_ps(dz10,fscal,fjz0);
1128
1129             /**************************
1130              * CALCULATE INTERACTIONS *
1131              **************************/
1132
1133             r20              = _mm_mul_ps(rsq20,rinv20);
1134             r20              = _mm_andnot_ps(dummy_mask,r20);
1135
1136             /* Compute parameters for interactions between i and j atoms */
1137             qq20             = _mm_mul_ps(iq2,jq0);
1138
1139             /* Calculate table index by multiplying r with table scale and truncate to integer */
1140             rt               = _mm_mul_ps(r20,vftabscale);
1141             vfitab           = _mm_cvttps_epi32(rt);
1142 #ifdef __XOP__
1143             vfeps            = _mm_frcz_ps(rt);
1144 #else
1145             vfeps            = _mm_sub_ps(rt,_mm_round_ps(rt, _MM_FROUND_FLOOR));
1146 #endif
1147             twovfeps         = _mm_add_ps(vfeps,vfeps);
1148             vfitab           = _mm_slli_epi32(vfitab,2);
1149
1150             /* CUBIC SPLINE TABLE ELECTROSTATICS */
1151             Y                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,0) );
1152             F                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,1) );
1153             G                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,2) );
1154             H                = _mm_load_ps( vftab + _mm_extract_epi32(vfitab,3) );
1155             _MM_TRANSPOSE4_PS(Y,F,G,H);
1156             Fp               = _mm_macc_ps(vfeps,_mm_macc_ps(H,vfeps,G),F);
1157             FF               = _mm_macc_ps(vfeps,_mm_macc_ps(twovfeps,H,G),Fp);
1158             felec            = _mm_xor_ps(signbit,_mm_mul_ps(_mm_mul_ps(qq20,FF),_mm_mul_ps(vftabscale,rinv20)));
1159
1160             fscal            = felec;
1161
1162             fscal            = _mm_andnot_ps(dummy_mask,fscal);
1163
1164              /* Update vectorial force */
1165             fix2             = _mm_macc_ps(dx20,fscal,fix2);
1166             fiy2             = _mm_macc_ps(dy20,fscal,fiy2);
1167             fiz2             = _mm_macc_ps(dz20,fscal,fiz2);
1168
1169             fjx0             = _mm_macc_ps(dx20,fscal,fjx0);
1170             fjy0             = _mm_macc_ps(dy20,fscal,fjy0);
1171             fjz0             = _mm_macc_ps(dz20,fscal,fjz0);
1172
1173             fjptrA             = (jnrlistA>=0) ? f+j_coord_offsetA : scratch;
1174             fjptrB             = (jnrlistB>=0) ? f+j_coord_offsetB : scratch;
1175             fjptrC             = (jnrlistC>=0) ? f+j_coord_offsetC : scratch;
1176             fjptrD             = (jnrlistD>=0) ? f+j_coord_offsetD : scratch;
1177
1178             gmx_mm_decrement_1rvec_4ptr_swizzle_ps(fjptrA,fjptrB,fjptrC,fjptrD,fjx0,fjy0,fjz0);
1179
1180             /* Inner loop uses 137 flops */
1181         }
1182
1183         /* End of innermost loop */
1184
1185         gmx_mm_update_iforce_3atom_swizzle_ps(fix0,fiy0,fiz0,fix1,fiy1,fiz1,fix2,fiy2,fiz2,
1186                                               f+i_coord_offset,fshift+i_shift_offset);
1187
1188         /* Increment number of inner iterations */
1189         inneriter                  += j_index_end - j_index_start;
1190
1191         /* Outer loop uses 18 flops */
1192     }
1193
1194     /* Increment number of outer iterations */
1195     outeriter        += nri;
1196
1197     /* Update outer/inner flops */
1198
1199     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_VDW_W3_F,outeriter*18 + inneriter*137);
1200 }