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