Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / gmxlib / nonbonded / nb_kernel_avx_128_fma_double / nb_kernel_ElecEwSw_VdwNone_GeomW4P1_avx_128_fma_double.c
1 /*
2  * Note: this file was generated by the Gromacs avx_128_fma_double 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_double.h"
34 #include "kernelutil_x86_avx_128_fma_double.h"
35
36 /*
37  * Gromacs nonbonded kernel:   nb_kernel_ElecEwSw_VdwNone_GeomW4P1_VF_avx_128_fma_double
38  * Electrostatics interaction: Ewald
39  * VdW interaction:            None
40  * Geometry:                   Water4-Particle
41  * Calculate force/pot:        PotentialAndForce
42  */
43 void
44 nb_kernel_ElecEwSw_VdwNone_GeomW4P1_VF_avx_128_fma_double
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 refer to j loop unrolling done with SSE double precision, e.g. for the two 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;
61     int              j_coord_offsetA,j_coord_offsetB;
62     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
63     real             rcutoff_scalar;
64     real             *shiftvec,*fshift,*x,*f;
65     __m128d          tx,ty,tz,fscal,rcutoff,rcutoff2,jidxall;
66     int              vdwioffset1;
67     __m128d          ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
68     int              vdwioffset2;
69     __m128d          ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
70     int              vdwioffset3;
71     __m128d          ix3,iy3,iz3,fix3,fiy3,fiz3,iq3,isai3;
72     int              vdwjidx0A,vdwjidx0B;
73     __m128d          jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
74     __m128d          dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10;
75     __m128d          dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20;
76     __m128d          dx30,dy30,dz30,rsq30,rinv30,rinvsq30,r30,qq30,c6_30,c12_30;
77     __m128d          velec,felec,velecsum,facel,crf,krf,krf2;
78     real             *charge;
79     __m128i          ewitab;
80     __m128d          ewtabscale,eweps,twoeweps,sh_ewald,ewrt,ewtabhalfspace,ewtabF,ewtabFn,ewtabD,ewtabV;
81     real             *ewtab;
82     __m128d          rswitch,swV3,swV4,swV5,swF2,swF3,swF4,d,d2,sw,dsw;
83     real             rswitch_scalar,d_scalar;
84     __m128d          dummy_mask,cutoff_mask;
85     __m128d          signbit   = gmx_mm_castsi128_pd( _mm_set_epi32(0x80000000,0x00000000,0x80000000,0x00000000) );
86     __m128d          one     = _mm_set1_pd(1.0);
87     __m128d          two     = _mm_set1_pd(2.0);
88     x                = xx[0];
89     f                = ff[0];
90
91     nri              = nlist->nri;
92     iinr             = nlist->iinr;
93     jindex           = nlist->jindex;
94     jjnr             = nlist->jjnr;
95     shiftidx         = nlist->shift;
96     gid              = nlist->gid;
97     shiftvec         = fr->shift_vec[0];
98     fshift           = fr->fshift[0];
99     facel            = _mm_set1_pd(fr->epsfac);
100     charge           = mdatoms->chargeA;
101
102     sh_ewald         = _mm_set1_pd(fr->ic->sh_ewald);
103     ewtab            = fr->ic->tabq_coul_FDV0;
104     ewtabscale       = _mm_set1_pd(fr->ic->tabq_scale);
105     ewtabhalfspace   = _mm_set1_pd(0.5/fr->ic->tabq_scale);
106
107     /* Setup water-specific parameters */
108     inr              = nlist->iinr[0];
109     iq1              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+1]));
110     iq2              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+2]));
111     iq3              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+3]));
112
113     /* When we use explicit cutoffs the value must be identical for elec and VdW, so use elec as an arbitrary choice */
114     rcutoff_scalar   = fr->rcoulomb;
115     rcutoff          = _mm_set1_pd(rcutoff_scalar);
116     rcutoff2         = _mm_mul_pd(rcutoff,rcutoff);
117
118     rswitch_scalar   = fr->rcoulomb_switch;
119     rswitch          = _mm_set1_pd(rswitch_scalar);
120     /* Setup switch parameters */
121     d_scalar         = rcutoff_scalar-rswitch_scalar;
122     d                = _mm_set1_pd(d_scalar);
123     swV3             = _mm_set1_pd(-10.0/(d_scalar*d_scalar*d_scalar));
124     swV4             = _mm_set1_pd( 15.0/(d_scalar*d_scalar*d_scalar*d_scalar));
125     swV5             = _mm_set1_pd( -6.0/(d_scalar*d_scalar*d_scalar*d_scalar*d_scalar));
126     swF2             = _mm_set1_pd(-30.0/(d_scalar*d_scalar*d_scalar));
127     swF3             = _mm_set1_pd( 60.0/(d_scalar*d_scalar*d_scalar*d_scalar));
128     swF4             = _mm_set1_pd(-30.0/(d_scalar*d_scalar*d_scalar*d_scalar*d_scalar));
129
130     /* Avoid stupid compiler warnings */
131     jnrA = jnrB = 0;
132     j_coord_offsetA = 0;
133     j_coord_offsetB = 0;
134
135     outeriter        = 0;
136     inneriter        = 0;
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_pd(shiftvec+i_shift_offset,x+i_coord_offset+DIM,
154                                                  &ix1,&iy1,&iz1,&ix2,&iy2,&iz2,&ix3,&iy3,&iz3);
155
156         fix1             = _mm_setzero_pd();
157         fiy1             = _mm_setzero_pd();
158         fiz1             = _mm_setzero_pd();
159         fix2             = _mm_setzero_pd();
160         fiy2             = _mm_setzero_pd();
161         fiz2             = _mm_setzero_pd();
162         fix3             = _mm_setzero_pd();
163         fiy3             = _mm_setzero_pd();
164         fiz3             = _mm_setzero_pd();
165
166         /* Reset potential sums */
167         velecsum         = _mm_setzero_pd();
168
169         /* Start inner kernel loop */
170         for(jidx=j_index_start; jidx<j_index_end-1; jidx+=2)
171         {
172
173             /* Get j neighbor index, and coordinate index */
174             jnrA             = jjnr[jidx];
175             jnrB             = jjnr[jidx+1];
176             j_coord_offsetA  = DIM*jnrA;
177             j_coord_offsetB  = DIM*jnrB;
178
179             /* load j atom coordinates */
180             gmx_mm_load_1rvec_2ptr_swizzle_pd(x+j_coord_offsetA,x+j_coord_offsetB,
181                                               &jx0,&jy0,&jz0);
182
183             /* Calculate displacement vector */
184             dx10             = _mm_sub_pd(ix1,jx0);
185             dy10             = _mm_sub_pd(iy1,jy0);
186             dz10             = _mm_sub_pd(iz1,jz0);
187             dx20             = _mm_sub_pd(ix2,jx0);
188             dy20             = _mm_sub_pd(iy2,jy0);
189             dz20             = _mm_sub_pd(iz2,jz0);
190             dx30             = _mm_sub_pd(ix3,jx0);
191             dy30             = _mm_sub_pd(iy3,jy0);
192             dz30             = _mm_sub_pd(iz3,jz0);
193
194             /* Calculate squared distance and things based on it */
195             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
196             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
197             rsq30            = gmx_mm_calc_rsq_pd(dx30,dy30,dz30);
198
199             rinv10           = gmx_mm_invsqrt_pd(rsq10);
200             rinv20           = gmx_mm_invsqrt_pd(rsq20);
201             rinv30           = gmx_mm_invsqrt_pd(rsq30);
202
203             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
204             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
205             rinvsq30         = _mm_mul_pd(rinv30,rinv30);
206
207             /* Load parameters for j particles */
208             jq0              = gmx_mm_load_2real_swizzle_pd(charge+jnrA+0,charge+jnrB+0);
209
210             fjx0             = _mm_setzero_pd();
211             fjy0             = _mm_setzero_pd();
212             fjz0             = _mm_setzero_pd();
213
214             /**************************
215              * CALCULATE INTERACTIONS *
216              **************************/
217
218             if (gmx_mm_any_lt(rsq10,rcutoff2))
219             {
220
221             r10              = _mm_mul_pd(rsq10,rinv10);
222
223             /* Compute parameters for interactions between i and j atoms */
224             qq10             = _mm_mul_pd(iq1,jq0);
225
226             /* EWALD ELECTROSTATICS */
227
228             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
229             ewrt             = _mm_mul_pd(r10,ewtabscale);
230             ewitab           = _mm_cvttpd_epi32(ewrt);
231 #ifdef __XOP__
232             eweps            = _mm_frcz_pd(ewrt);
233 #else
234             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
235 #endif
236             twoeweps         = _mm_add_pd(eweps,eweps);
237             ewitab           = _mm_slli_epi32(ewitab,2);
238             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
239             ewtabD           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,1) );
240             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
241             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
242             ewtabFn          = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,1) +2);
243             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
244             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
245             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
246             velec            = _mm_mul_pd(qq10,_mm_sub_pd(rinv10,velec));
247             felec            = _mm_mul_pd(_mm_mul_pd(qq10,rinv10),_mm_sub_pd(rinvsq10,felec));
248
249             d                = _mm_sub_pd(r10,rswitch);
250             d                = _mm_max_pd(d,_mm_setzero_pd());
251             d2               = _mm_mul_pd(d,d);
252             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
253
254             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
255
256             /* Evaluate switch function */
257             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
258             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv10,_mm_mul_pd(velec,dsw)) );
259             velec            = _mm_mul_pd(velec,sw);
260             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
261
262             /* Update potential sum for this i atom from the interaction with this j atom. */
263             velec            = _mm_and_pd(velec,cutoff_mask);
264             velecsum         = _mm_add_pd(velecsum,velec);
265
266             fscal            = felec;
267
268             fscal            = _mm_and_pd(fscal,cutoff_mask);
269
270             /* Update vectorial force */
271             fix1             = _mm_macc_pd(dx10,fscal,fix1);
272             fiy1             = _mm_macc_pd(dy10,fscal,fiy1);
273             fiz1             = _mm_macc_pd(dz10,fscal,fiz1);
274             
275             fjx0             = _mm_macc_pd(dx10,fscal,fjx0);
276             fjy0             = _mm_macc_pd(dy10,fscal,fjy0);
277             fjz0             = _mm_macc_pd(dz10,fscal,fjz0);
278
279             }
280
281             /**************************
282              * CALCULATE INTERACTIONS *
283              **************************/
284
285             if (gmx_mm_any_lt(rsq20,rcutoff2))
286             {
287
288             r20              = _mm_mul_pd(rsq20,rinv20);
289
290             /* Compute parameters for interactions between i and j atoms */
291             qq20             = _mm_mul_pd(iq2,jq0);
292
293             /* EWALD ELECTROSTATICS */
294
295             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
296             ewrt             = _mm_mul_pd(r20,ewtabscale);
297             ewitab           = _mm_cvttpd_epi32(ewrt);
298 #ifdef __XOP__
299             eweps            = _mm_frcz_pd(ewrt);
300 #else
301             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
302 #endif
303             twoeweps         = _mm_add_pd(eweps,eweps);
304             ewitab           = _mm_slli_epi32(ewitab,2);
305             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
306             ewtabD           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,1) );
307             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
308             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
309             ewtabFn          = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,1) +2);
310             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
311             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
312             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
313             velec            = _mm_mul_pd(qq20,_mm_sub_pd(rinv20,velec));
314             felec            = _mm_mul_pd(_mm_mul_pd(qq20,rinv20),_mm_sub_pd(rinvsq20,felec));
315
316             d                = _mm_sub_pd(r20,rswitch);
317             d                = _mm_max_pd(d,_mm_setzero_pd());
318             d2               = _mm_mul_pd(d,d);
319             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
320
321             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
322
323             /* Evaluate switch function */
324             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
325             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv20,_mm_mul_pd(velec,dsw)) );
326             velec            = _mm_mul_pd(velec,sw);
327             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
328
329             /* Update potential sum for this i atom from the interaction with this j atom. */
330             velec            = _mm_and_pd(velec,cutoff_mask);
331             velecsum         = _mm_add_pd(velecsum,velec);
332
333             fscal            = felec;
334
335             fscal            = _mm_and_pd(fscal,cutoff_mask);
336
337             /* Update vectorial force */
338             fix2             = _mm_macc_pd(dx20,fscal,fix2);
339             fiy2             = _mm_macc_pd(dy20,fscal,fiy2);
340             fiz2             = _mm_macc_pd(dz20,fscal,fiz2);
341             
342             fjx0             = _mm_macc_pd(dx20,fscal,fjx0);
343             fjy0             = _mm_macc_pd(dy20,fscal,fjy0);
344             fjz0             = _mm_macc_pd(dz20,fscal,fjz0);
345
346             }
347
348             /**************************
349              * CALCULATE INTERACTIONS *
350              **************************/
351
352             if (gmx_mm_any_lt(rsq30,rcutoff2))
353             {
354
355             r30              = _mm_mul_pd(rsq30,rinv30);
356
357             /* Compute parameters for interactions between i and j atoms */
358             qq30             = _mm_mul_pd(iq3,jq0);
359
360             /* EWALD ELECTROSTATICS */
361
362             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
363             ewrt             = _mm_mul_pd(r30,ewtabscale);
364             ewitab           = _mm_cvttpd_epi32(ewrt);
365 #ifdef __XOP__
366             eweps            = _mm_frcz_pd(ewrt);
367 #else
368             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
369 #endif
370             twoeweps         = _mm_add_pd(eweps,eweps);
371             ewitab           = _mm_slli_epi32(ewitab,2);
372             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
373             ewtabD           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,1) );
374             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
375             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
376             ewtabFn          = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,1) +2);
377             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
378             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
379             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
380             velec            = _mm_mul_pd(qq30,_mm_sub_pd(rinv30,velec));
381             felec            = _mm_mul_pd(_mm_mul_pd(qq30,rinv30),_mm_sub_pd(rinvsq30,felec));
382
383             d                = _mm_sub_pd(r30,rswitch);
384             d                = _mm_max_pd(d,_mm_setzero_pd());
385             d2               = _mm_mul_pd(d,d);
386             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
387
388             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
389
390             /* Evaluate switch function */
391             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
392             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv30,_mm_mul_pd(velec,dsw)) );
393             velec            = _mm_mul_pd(velec,sw);
394             cutoff_mask      = _mm_cmplt_pd(rsq30,rcutoff2);
395
396             /* Update potential sum for this i atom from the interaction with this j atom. */
397             velec            = _mm_and_pd(velec,cutoff_mask);
398             velecsum         = _mm_add_pd(velecsum,velec);
399
400             fscal            = felec;
401
402             fscal            = _mm_and_pd(fscal,cutoff_mask);
403
404             /* Update vectorial force */
405             fix3             = _mm_macc_pd(dx30,fscal,fix3);
406             fiy3             = _mm_macc_pd(dy30,fscal,fiy3);
407             fiz3             = _mm_macc_pd(dz30,fscal,fiz3);
408             
409             fjx0             = _mm_macc_pd(dx30,fscal,fjx0);
410             fjy0             = _mm_macc_pd(dy30,fscal,fjy0);
411             fjz0             = _mm_macc_pd(dz30,fscal,fjz0);
412
413             }
414
415             gmx_mm_decrement_1rvec_2ptr_swizzle_pd(f+j_coord_offsetA,f+j_coord_offsetB,fjx0,fjy0,fjz0);
416
417             /* Inner loop uses 207 flops */
418         }
419
420         if(jidx<j_index_end)
421         {
422
423             jnrA             = jjnr[jidx];
424             j_coord_offsetA  = DIM*jnrA;
425
426             /* load j atom coordinates */
427             gmx_mm_load_1rvec_1ptr_swizzle_pd(x+j_coord_offsetA,
428                                               &jx0,&jy0,&jz0);
429
430             /* Calculate displacement vector */
431             dx10             = _mm_sub_pd(ix1,jx0);
432             dy10             = _mm_sub_pd(iy1,jy0);
433             dz10             = _mm_sub_pd(iz1,jz0);
434             dx20             = _mm_sub_pd(ix2,jx0);
435             dy20             = _mm_sub_pd(iy2,jy0);
436             dz20             = _mm_sub_pd(iz2,jz0);
437             dx30             = _mm_sub_pd(ix3,jx0);
438             dy30             = _mm_sub_pd(iy3,jy0);
439             dz30             = _mm_sub_pd(iz3,jz0);
440
441             /* Calculate squared distance and things based on it */
442             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
443             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
444             rsq30            = gmx_mm_calc_rsq_pd(dx30,dy30,dz30);
445
446             rinv10           = gmx_mm_invsqrt_pd(rsq10);
447             rinv20           = gmx_mm_invsqrt_pd(rsq20);
448             rinv30           = gmx_mm_invsqrt_pd(rsq30);
449
450             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
451             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
452             rinvsq30         = _mm_mul_pd(rinv30,rinv30);
453
454             /* Load parameters for j particles */
455             jq0              = _mm_load_sd(charge+jnrA+0);
456
457             fjx0             = _mm_setzero_pd();
458             fjy0             = _mm_setzero_pd();
459             fjz0             = _mm_setzero_pd();
460
461             /**************************
462              * CALCULATE INTERACTIONS *
463              **************************/
464
465             if (gmx_mm_any_lt(rsq10,rcutoff2))
466             {
467
468             r10              = _mm_mul_pd(rsq10,rinv10);
469
470             /* Compute parameters for interactions between i and j atoms */
471             qq10             = _mm_mul_pd(iq1,jq0);
472
473             /* EWALD ELECTROSTATICS */
474
475             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
476             ewrt             = _mm_mul_pd(r10,ewtabscale);
477             ewitab           = _mm_cvttpd_epi32(ewrt);
478 #ifdef __XOP__
479             eweps            = _mm_frcz_pd(ewrt);
480 #else
481             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
482 #endif
483             twoeweps         = _mm_add_pd(eweps,eweps);
484             ewitab           = _mm_slli_epi32(ewitab,2);
485             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
486             ewtabD           = _mm_setzero_pd();
487             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
488             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
489             ewtabFn          = _mm_setzero_pd();
490             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
491             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
492             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
493             velec            = _mm_mul_pd(qq10,_mm_sub_pd(rinv10,velec));
494             felec            = _mm_mul_pd(_mm_mul_pd(qq10,rinv10),_mm_sub_pd(rinvsq10,felec));
495
496             d                = _mm_sub_pd(r10,rswitch);
497             d                = _mm_max_pd(d,_mm_setzero_pd());
498             d2               = _mm_mul_pd(d,d);
499             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
500
501             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
502
503             /* Evaluate switch function */
504             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
505             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv10,_mm_mul_pd(velec,dsw)) );
506             velec            = _mm_mul_pd(velec,sw);
507             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
508
509             /* Update potential sum for this i atom from the interaction with this j atom. */
510             velec            = _mm_and_pd(velec,cutoff_mask);
511             velec            = _mm_unpacklo_pd(velec,_mm_setzero_pd());
512             velecsum         = _mm_add_pd(velecsum,velec);
513
514             fscal            = felec;
515
516             fscal            = _mm_and_pd(fscal,cutoff_mask);
517
518             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
519
520             /* Update vectorial force */
521             fix1             = _mm_macc_pd(dx10,fscal,fix1);
522             fiy1             = _mm_macc_pd(dy10,fscal,fiy1);
523             fiz1             = _mm_macc_pd(dz10,fscal,fiz1);
524             
525             fjx0             = _mm_macc_pd(dx10,fscal,fjx0);
526             fjy0             = _mm_macc_pd(dy10,fscal,fjy0);
527             fjz0             = _mm_macc_pd(dz10,fscal,fjz0);
528
529             }
530
531             /**************************
532              * CALCULATE INTERACTIONS *
533              **************************/
534
535             if (gmx_mm_any_lt(rsq20,rcutoff2))
536             {
537
538             r20              = _mm_mul_pd(rsq20,rinv20);
539
540             /* Compute parameters for interactions between i and j atoms */
541             qq20             = _mm_mul_pd(iq2,jq0);
542
543             /* EWALD ELECTROSTATICS */
544
545             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
546             ewrt             = _mm_mul_pd(r20,ewtabscale);
547             ewitab           = _mm_cvttpd_epi32(ewrt);
548 #ifdef __XOP__
549             eweps            = _mm_frcz_pd(ewrt);
550 #else
551             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
552 #endif
553             twoeweps         = _mm_add_pd(eweps,eweps);
554             ewitab           = _mm_slli_epi32(ewitab,2);
555             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
556             ewtabD           = _mm_setzero_pd();
557             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
558             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
559             ewtabFn          = _mm_setzero_pd();
560             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
561             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
562             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
563             velec            = _mm_mul_pd(qq20,_mm_sub_pd(rinv20,velec));
564             felec            = _mm_mul_pd(_mm_mul_pd(qq20,rinv20),_mm_sub_pd(rinvsq20,felec));
565
566             d                = _mm_sub_pd(r20,rswitch);
567             d                = _mm_max_pd(d,_mm_setzero_pd());
568             d2               = _mm_mul_pd(d,d);
569             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
570
571             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
572
573             /* Evaluate switch function */
574             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
575             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv20,_mm_mul_pd(velec,dsw)) );
576             velec            = _mm_mul_pd(velec,sw);
577             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
578
579             /* Update potential sum for this i atom from the interaction with this j atom. */
580             velec            = _mm_and_pd(velec,cutoff_mask);
581             velec            = _mm_unpacklo_pd(velec,_mm_setzero_pd());
582             velecsum         = _mm_add_pd(velecsum,velec);
583
584             fscal            = felec;
585
586             fscal            = _mm_and_pd(fscal,cutoff_mask);
587
588             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
589
590             /* Update vectorial force */
591             fix2             = _mm_macc_pd(dx20,fscal,fix2);
592             fiy2             = _mm_macc_pd(dy20,fscal,fiy2);
593             fiz2             = _mm_macc_pd(dz20,fscal,fiz2);
594             
595             fjx0             = _mm_macc_pd(dx20,fscal,fjx0);
596             fjy0             = _mm_macc_pd(dy20,fscal,fjy0);
597             fjz0             = _mm_macc_pd(dz20,fscal,fjz0);
598
599             }
600
601             /**************************
602              * CALCULATE INTERACTIONS *
603              **************************/
604
605             if (gmx_mm_any_lt(rsq30,rcutoff2))
606             {
607
608             r30              = _mm_mul_pd(rsq30,rinv30);
609
610             /* Compute parameters for interactions between i and j atoms */
611             qq30             = _mm_mul_pd(iq3,jq0);
612
613             /* EWALD ELECTROSTATICS */
614
615             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
616             ewrt             = _mm_mul_pd(r30,ewtabscale);
617             ewitab           = _mm_cvttpd_epi32(ewrt);
618 #ifdef __XOP__
619             eweps            = _mm_frcz_pd(ewrt);
620 #else
621             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
622 #endif
623             twoeweps         = _mm_add_pd(eweps,eweps);
624             ewitab           = _mm_slli_epi32(ewitab,2);
625             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
626             ewtabD           = _mm_setzero_pd();
627             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
628             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
629             ewtabFn          = _mm_setzero_pd();
630             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
631             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
632             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
633             velec            = _mm_mul_pd(qq30,_mm_sub_pd(rinv30,velec));
634             felec            = _mm_mul_pd(_mm_mul_pd(qq30,rinv30),_mm_sub_pd(rinvsq30,felec));
635
636             d                = _mm_sub_pd(r30,rswitch);
637             d                = _mm_max_pd(d,_mm_setzero_pd());
638             d2               = _mm_mul_pd(d,d);
639             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
640
641             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
642
643             /* Evaluate switch function */
644             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
645             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv30,_mm_mul_pd(velec,dsw)) );
646             velec            = _mm_mul_pd(velec,sw);
647             cutoff_mask      = _mm_cmplt_pd(rsq30,rcutoff2);
648
649             /* Update potential sum for this i atom from the interaction with this j atom. */
650             velec            = _mm_and_pd(velec,cutoff_mask);
651             velec            = _mm_unpacklo_pd(velec,_mm_setzero_pd());
652             velecsum         = _mm_add_pd(velecsum,velec);
653
654             fscal            = felec;
655
656             fscal            = _mm_and_pd(fscal,cutoff_mask);
657
658             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
659
660             /* Update vectorial force */
661             fix3             = _mm_macc_pd(dx30,fscal,fix3);
662             fiy3             = _mm_macc_pd(dy30,fscal,fiy3);
663             fiz3             = _mm_macc_pd(dz30,fscal,fiz3);
664             
665             fjx0             = _mm_macc_pd(dx30,fscal,fjx0);
666             fjy0             = _mm_macc_pd(dy30,fscal,fjy0);
667             fjz0             = _mm_macc_pd(dz30,fscal,fjz0);
668
669             }
670
671             gmx_mm_decrement_1rvec_1ptr_swizzle_pd(f+j_coord_offsetA,fjx0,fjy0,fjz0);
672
673             /* Inner loop uses 207 flops */
674         }
675
676         /* End of innermost loop */
677
678         gmx_mm_update_iforce_3atom_swizzle_pd(fix1,fiy1,fiz1,fix2,fiy2,fiz2,fix3,fiy3,fiz3,
679                                               f+i_coord_offset+DIM,fshift+i_shift_offset);
680
681         ggid                        = gid[iidx];
682         /* Update potential energies */
683         gmx_mm_update_1pot_pd(velecsum,kernel_data->energygrp_elec+ggid);
684
685         /* Increment number of inner iterations */
686         inneriter                  += j_index_end - j_index_start;
687
688         /* Outer loop uses 19 flops */
689     }
690
691     /* Increment number of outer iterations */
692     outeriter        += nri;
693
694     /* Update outer/inner flops */
695
696     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_W4_VF,outeriter*19 + inneriter*207);
697 }
698 /*
699  * Gromacs nonbonded kernel:   nb_kernel_ElecEwSw_VdwNone_GeomW4P1_F_avx_128_fma_double
700  * Electrostatics interaction: Ewald
701  * VdW interaction:            None
702  * Geometry:                   Water4-Particle
703  * Calculate force/pot:        Force
704  */
705 void
706 nb_kernel_ElecEwSw_VdwNone_GeomW4P1_F_avx_128_fma_double
707                     (t_nblist * gmx_restrict                nlist,
708                      rvec * gmx_restrict                    xx,
709                      rvec * gmx_restrict                    ff,
710                      t_forcerec * gmx_restrict              fr,
711                      t_mdatoms * gmx_restrict               mdatoms,
712                      nb_kernel_data_t * gmx_restrict        kernel_data,
713                      t_nrnb * gmx_restrict                  nrnb)
714 {
715     /* Suffixes 0,1,2,3 refer to particle indices for waters in the inner or outer loop, or
716      * just 0 for non-waters.
717      * Suffixes A,B refer to j loop unrolling done with SSE double precision, e.g. for the two different
718      * jnr indices corresponding to data put in the four positions in the SIMD register.
719      */
720     int              i_shift_offset,i_coord_offset,outeriter,inneriter;
721     int              j_index_start,j_index_end,jidx,nri,inr,ggid,iidx;
722     int              jnrA,jnrB;
723     int              j_coord_offsetA,j_coord_offsetB;
724     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
725     real             rcutoff_scalar;
726     real             *shiftvec,*fshift,*x,*f;
727     __m128d          tx,ty,tz,fscal,rcutoff,rcutoff2,jidxall;
728     int              vdwioffset1;
729     __m128d          ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
730     int              vdwioffset2;
731     __m128d          ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
732     int              vdwioffset3;
733     __m128d          ix3,iy3,iz3,fix3,fiy3,fiz3,iq3,isai3;
734     int              vdwjidx0A,vdwjidx0B;
735     __m128d          jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
736     __m128d          dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10;
737     __m128d          dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20;
738     __m128d          dx30,dy30,dz30,rsq30,rinv30,rinvsq30,r30,qq30,c6_30,c12_30;
739     __m128d          velec,felec,velecsum,facel,crf,krf,krf2;
740     real             *charge;
741     __m128i          ewitab;
742     __m128d          ewtabscale,eweps,twoeweps,sh_ewald,ewrt,ewtabhalfspace,ewtabF,ewtabFn,ewtabD,ewtabV;
743     real             *ewtab;
744     __m128d          rswitch,swV3,swV4,swV5,swF2,swF3,swF4,d,d2,sw,dsw;
745     real             rswitch_scalar,d_scalar;
746     __m128d          dummy_mask,cutoff_mask;
747     __m128d          signbit   = gmx_mm_castsi128_pd( _mm_set_epi32(0x80000000,0x00000000,0x80000000,0x00000000) );
748     __m128d          one     = _mm_set1_pd(1.0);
749     __m128d          two     = _mm_set1_pd(2.0);
750     x                = xx[0];
751     f                = ff[0];
752
753     nri              = nlist->nri;
754     iinr             = nlist->iinr;
755     jindex           = nlist->jindex;
756     jjnr             = nlist->jjnr;
757     shiftidx         = nlist->shift;
758     gid              = nlist->gid;
759     shiftvec         = fr->shift_vec[0];
760     fshift           = fr->fshift[0];
761     facel            = _mm_set1_pd(fr->epsfac);
762     charge           = mdatoms->chargeA;
763
764     sh_ewald         = _mm_set1_pd(fr->ic->sh_ewald);
765     ewtab            = fr->ic->tabq_coul_FDV0;
766     ewtabscale       = _mm_set1_pd(fr->ic->tabq_scale);
767     ewtabhalfspace   = _mm_set1_pd(0.5/fr->ic->tabq_scale);
768
769     /* Setup water-specific parameters */
770     inr              = nlist->iinr[0];
771     iq1              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+1]));
772     iq2              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+2]));
773     iq3              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+3]));
774
775     /* When we use explicit cutoffs the value must be identical for elec and VdW, so use elec as an arbitrary choice */
776     rcutoff_scalar   = fr->rcoulomb;
777     rcutoff          = _mm_set1_pd(rcutoff_scalar);
778     rcutoff2         = _mm_mul_pd(rcutoff,rcutoff);
779
780     rswitch_scalar   = fr->rcoulomb_switch;
781     rswitch          = _mm_set1_pd(rswitch_scalar);
782     /* Setup switch parameters */
783     d_scalar         = rcutoff_scalar-rswitch_scalar;
784     d                = _mm_set1_pd(d_scalar);
785     swV3             = _mm_set1_pd(-10.0/(d_scalar*d_scalar*d_scalar));
786     swV4             = _mm_set1_pd( 15.0/(d_scalar*d_scalar*d_scalar*d_scalar));
787     swV5             = _mm_set1_pd( -6.0/(d_scalar*d_scalar*d_scalar*d_scalar*d_scalar));
788     swF2             = _mm_set1_pd(-30.0/(d_scalar*d_scalar*d_scalar));
789     swF3             = _mm_set1_pd( 60.0/(d_scalar*d_scalar*d_scalar*d_scalar));
790     swF4             = _mm_set1_pd(-30.0/(d_scalar*d_scalar*d_scalar*d_scalar*d_scalar));
791
792     /* Avoid stupid compiler warnings */
793     jnrA = jnrB = 0;
794     j_coord_offsetA = 0;
795     j_coord_offsetB = 0;
796
797     outeriter        = 0;
798     inneriter        = 0;
799
800     /* Start outer loop over neighborlists */
801     for(iidx=0; iidx<nri; iidx++)
802     {
803         /* Load shift vector for this list */
804         i_shift_offset   = DIM*shiftidx[iidx];
805
806         /* Load limits for loop over neighbors */
807         j_index_start    = jindex[iidx];
808         j_index_end      = jindex[iidx+1];
809
810         /* Get outer coordinate index */
811         inr              = iinr[iidx];
812         i_coord_offset   = DIM*inr;
813
814         /* Load i particle coords and add shift vector */
815         gmx_mm_load_shift_and_3rvec_broadcast_pd(shiftvec+i_shift_offset,x+i_coord_offset+DIM,
816                                                  &ix1,&iy1,&iz1,&ix2,&iy2,&iz2,&ix3,&iy3,&iz3);
817
818         fix1             = _mm_setzero_pd();
819         fiy1             = _mm_setzero_pd();
820         fiz1             = _mm_setzero_pd();
821         fix2             = _mm_setzero_pd();
822         fiy2             = _mm_setzero_pd();
823         fiz2             = _mm_setzero_pd();
824         fix3             = _mm_setzero_pd();
825         fiy3             = _mm_setzero_pd();
826         fiz3             = _mm_setzero_pd();
827
828         /* Start inner kernel loop */
829         for(jidx=j_index_start; jidx<j_index_end-1; jidx+=2)
830         {
831
832             /* Get j neighbor index, and coordinate index */
833             jnrA             = jjnr[jidx];
834             jnrB             = jjnr[jidx+1];
835             j_coord_offsetA  = DIM*jnrA;
836             j_coord_offsetB  = DIM*jnrB;
837
838             /* load j atom coordinates */
839             gmx_mm_load_1rvec_2ptr_swizzle_pd(x+j_coord_offsetA,x+j_coord_offsetB,
840                                               &jx0,&jy0,&jz0);
841
842             /* Calculate displacement vector */
843             dx10             = _mm_sub_pd(ix1,jx0);
844             dy10             = _mm_sub_pd(iy1,jy0);
845             dz10             = _mm_sub_pd(iz1,jz0);
846             dx20             = _mm_sub_pd(ix2,jx0);
847             dy20             = _mm_sub_pd(iy2,jy0);
848             dz20             = _mm_sub_pd(iz2,jz0);
849             dx30             = _mm_sub_pd(ix3,jx0);
850             dy30             = _mm_sub_pd(iy3,jy0);
851             dz30             = _mm_sub_pd(iz3,jz0);
852
853             /* Calculate squared distance and things based on it */
854             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
855             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
856             rsq30            = gmx_mm_calc_rsq_pd(dx30,dy30,dz30);
857
858             rinv10           = gmx_mm_invsqrt_pd(rsq10);
859             rinv20           = gmx_mm_invsqrt_pd(rsq20);
860             rinv30           = gmx_mm_invsqrt_pd(rsq30);
861
862             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
863             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
864             rinvsq30         = _mm_mul_pd(rinv30,rinv30);
865
866             /* Load parameters for j particles */
867             jq0              = gmx_mm_load_2real_swizzle_pd(charge+jnrA+0,charge+jnrB+0);
868
869             fjx0             = _mm_setzero_pd();
870             fjy0             = _mm_setzero_pd();
871             fjz0             = _mm_setzero_pd();
872
873             /**************************
874              * CALCULATE INTERACTIONS *
875              **************************/
876
877             if (gmx_mm_any_lt(rsq10,rcutoff2))
878             {
879
880             r10              = _mm_mul_pd(rsq10,rinv10);
881
882             /* Compute parameters for interactions between i and j atoms */
883             qq10             = _mm_mul_pd(iq1,jq0);
884
885             /* EWALD ELECTROSTATICS */
886
887             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
888             ewrt             = _mm_mul_pd(r10,ewtabscale);
889             ewitab           = _mm_cvttpd_epi32(ewrt);
890 #ifdef __XOP__
891             eweps            = _mm_frcz_pd(ewrt);
892 #else
893             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
894 #endif
895             twoeweps         = _mm_add_pd(eweps,eweps);
896             ewitab           = _mm_slli_epi32(ewitab,2);
897             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
898             ewtabD           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,1) );
899             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
900             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
901             ewtabFn          = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,1) +2);
902             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
903             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
904             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
905             velec            = _mm_mul_pd(qq10,_mm_sub_pd(rinv10,velec));
906             felec            = _mm_mul_pd(_mm_mul_pd(qq10,rinv10),_mm_sub_pd(rinvsq10,felec));
907
908             d                = _mm_sub_pd(r10,rswitch);
909             d                = _mm_max_pd(d,_mm_setzero_pd());
910             d2               = _mm_mul_pd(d,d);
911             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
912
913             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
914
915             /* Evaluate switch function */
916             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
917             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv10,_mm_mul_pd(velec,dsw)) );
918             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
919
920             fscal            = felec;
921
922             fscal            = _mm_and_pd(fscal,cutoff_mask);
923
924             /* Update vectorial force */
925             fix1             = _mm_macc_pd(dx10,fscal,fix1);
926             fiy1             = _mm_macc_pd(dy10,fscal,fiy1);
927             fiz1             = _mm_macc_pd(dz10,fscal,fiz1);
928             
929             fjx0             = _mm_macc_pd(dx10,fscal,fjx0);
930             fjy0             = _mm_macc_pd(dy10,fscal,fjy0);
931             fjz0             = _mm_macc_pd(dz10,fscal,fjz0);
932
933             }
934
935             /**************************
936              * CALCULATE INTERACTIONS *
937              **************************/
938
939             if (gmx_mm_any_lt(rsq20,rcutoff2))
940             {
941
942             r20              = _mm_mul_pd(rsq20,rinv20);
943
944             /* Compute parameters for interactions between i and j atoms */
945             qq20             = _mm_mul_pd(iq2,jq0);
946
947             /* EWALD ELECTROSTATICS */
948
949             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
950             ewrt             = _mm_mul_pd(r20,ewtabscale);
951             ewitab           = _mm_cvttpd_epi32(ewrt);
952 #ifdef __XOP__
953             eweps            = _mm_frcz_pd(ewrt);
954 #else
955             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
956 #endif
957             twoeweps         = _mm_add_pd(eweps,eweps);
958             ewitab           = _mm_slli_epi32(ewitab,2);
959             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
960             ewtabD           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,1) );
961             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
962             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
963             ewtabFn          = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,1) +2);
964             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
965             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
966             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
967             velec            = _mm_mul_pd(qq20,_mm_sub_pd(rinv20,velec));
968             felec            = _mm_mul_pd(_mm_mul_pd(qq20,rinv20),_mm_sub_pd(rinvsq20,felec));
969
970             d                = _mm_sub_pd(r20,rswitch);
971             d                = _mm_max_pd(d,_mm_setzero_pd());
972             d2               = _mm_mul_pd(d,d);
973             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
974
975             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
976
977             /* Evaluate switch function */
978             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
979             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv20,_mm_mul_pd(velec,dsw)) );
980             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
981
982             fscal            = felec;
983
984             fscal            = _mm_and_pd(fscal,cutoff_mask);
985
986             /* Update vectorial force */
987             fix2             = _mm_macc_pd(dx20,fscal,fix2);
988             fiy2             = _mm_macc_pd(dy20,fscal,fiy2);
989             fiz2             = _mm_macc_pd(dz20,fscal,fiz2);
990             
991             fjx0             = _mm_macc_pd(dx20,fscal,fjx0);
992             fjy0             = _mm_macc_pd(dy20,fscal,fjy0);
993             fjz0             = _mm_macc_pd(dz20,fscal,fjz0);
994
995             }
996
997             /**************************
998              * CALCULATE INTERACTIONS *
999              **************************/
1000
1001             if (gmx_mm_any_lt(rsq30,rcutoff2))
1002             {
1003
1004             r30              = _mm_mul_pd(rsq30,rinv30);
1005
1006             /* Compute parameters for interactions between i and j atoms */
1007             qq30             = _mm_mul_pd(iq3,jq0);
1008
1009             /* EWALD ELECTROSTATICS */
1010
1011             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
1012             ewrt             = _mm_mul_pd(r30,ewtabscale);
1013             ewitab           = _mm_cvttpd_epi32(ewrt);
1014 #ifdef __XOP__
1015             eweps            = _mm_frcz_pd(ewrt);
1016 #else
1017             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
1018 #endif
1019             twoeweps         = _mm_add_pd(eweps,eweps);
1020             ewitab           = _mm_slli_epi32(ewitab,2);
1021             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
1022             ewtabD           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,1) );
1023             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
1024             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
1025             ewtabFn          = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,1) +2);
1026             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
1027             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
1028             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
1029             velec            = _mm_mul_pd(qq30,_mm_sub_pd(rinv30,velec));
1030             felec            = _mm_mul_pd(_mm_mul_pd(qq30,rinv30),_mm_sub_pd(rinvsq30,felec));
1031
1032             d                = _mm_sub_pd(r30,rswitch);
1033             d                = _mm_max_pd(d,_mm_setzero_pd());
1034             d2               = _mm_mul_pd(d,d);
1035             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
1036
1037             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
1038
1039             /* Evaluate switch function */
1040             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
1041             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv30,_mm_mul_pd(velec,dsw)) );
1042             cutoff_mask      = _mm_cmplt_pd(rsq30,rcutoff2);
1043
1044             fscal            = felec;
1045
1046             fscal            = _mm_and_pd(fscal,cutoff_mask);
1047
1048             /* Update vectorial force */
1049             fix3             = _mm_macc_pd(dx30,fscal,fix3);
1050             fiy3             = _mm_macc_pd(dy30,fscal,fiy3);
1051             fiz3             = _mm_macc_pd(dz30,fscal,fiz3);
1052             
1053             fjx0             = _mm_macc_pd(dx30,fscal,fjx0);
1054             fjy0             = _mm_macc_pd(dy30,fscal,fjy0);
1055             fjz0             = _mm_macc_pd(dz30,fscal,fjz0);
1056
1057             }
1058
1059             gmx_mm_decrement_1rvec_2ptr_swizzle_pd(f+j_coord_offsetA,f+j_coord_offsetB,fjx0,fjy0,fjz0);
1060
1061             /* Inner loop uses 198 flops */
1062         }
1063
1064         if(jidx<j_index_end)
1065         {
1066
1067             jnrA             = jjnr[jidx];
1068             j_coord_offsetA  = DIM*jnrA;
1069
1070             /* load j atom coordinates */
1071             gmx_mm_load_1rvec_1ptr_swizzle_pd(x+j_coord_offsetA,
1072                                               &jx0,&jy0,&jz0);
1073
1074             /* Calculate displacement vector */
1075             dx10             = _mm_sub_pd(ix1,jx0);
1076             dy10             = _mm_sub_pd(iy1,jy0);
1077             dz10             = _mm_sub_pd(iz1,jz0);
1078             dx20             = _mm_sub_pd(ix2,jx0);
1079             dy20             = _mm_sub_pd(iy2,jy0);
1080             dz20             = _mm_sub_pd(iz2,jz0);
1081             dx30             = _mm_sub_pd(ix3,jx0);
1082             dy30             = _mm_sub_pd(iy3,jy0);
1083             dz30             = _mm_sub_pd(iz3,jz0);
1084
1085             /* Calculate squared distance and things based on it */
1086             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
1087             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
1088             rsq30            = gmx_mm_calc_rsq_pd(dx30,dy30,dz30);
1089
1090             rinv10           = gmx_mm_invsqrt_pd(rsq10);
1091             rinv20           = gmx_mm_invsqrt_pd(rsq20);
1092             rinv30           = gmx_mm_invsqrt_pd(rsq30);
1093
1094             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
1095             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
1096             rinvsq30         = _mm_mul_pd(rinv30,rinv30);
1097
1098             /* Load parameters for j particles */
1099             jq0              = _mm_load_sd(charge+jnrA+0);
1100
1101             fjx0             = _mm_setzero_pd();
1102             fjy0             = _mm_setzero_pd();
1103             fjz0             = _mm_setzero_pd();
1104
1105             /**************************
1106              * CALCULATE INTERACTIONS *
1107              **************************/
1108
1109             if (gmx_mm_any_lt(rsq10,rcutoff2))
1110             {
1111
1112             r10              = _mm_mul_pd(rsq10,rinv10);
1113
1114             /* Compute parameters for interactions between i and j atoms */
1115             qq10             = _mm_mul_pd(iq1,jq0);
1116
1117             /* EWALD ELECTROSTATICS */
1118
1119             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
1120             ewrt             = _mm_mul_pd(r10,ewtabscale);
1121             ewitab           = _mm_cvttpd_epi32(ewrt);
1122 #ifdef __XOP__
1123             eweps            = _mm_frcz_pd(ewrt);
1124 #else
1125             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
1126 #endif
1127             twoeweps         = _mm_add_pd(eweps,eweps);
1128             ewitab           = _mm_slli_epi32(ewitab,2);
1129             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
1130             ewtabD           = _mm_setzero_pd();
1131             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
1132             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
1133             ewtabFn          = _mm_setzero_pd();
1134             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
1135             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
1136             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
1137             velec            = _mm_mul_pd(qq10,_mm_sub_pd(rinv10,velec));
1138             felec            = _mm_mul_pd(_mm_mul_pd(qq10,rinv10),_mm_sub_pd(rinvsq10,felec));
1139
1140             d                = _mm_sub_pd(r10,rswitch);
1141             d                = _mm_max_pd(d,_mm_setzero_pd());
1142             d2               = _mm_mul_pd(d,d);
1143             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
1144
1145             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
1146
1147             /* Evaluate switch function */
1148             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
1149             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv10,_mm_mul_pd(velec,dsw)) );
1150             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
1151
1152             fscal            = felec;
1153
1154             fscal            = _mm_and_pd(fscal,cutoff_mask);
1155
1156             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
1157
1158             /* Update vectorial force */
1159             fix1             = _mm_macc_pd(dx10,fscal,fix1);
1160             fiy1             = _mm_macc_pd(dy10,fscal,fiy1);
1161             fiz1             = _mm_macc_pd(dz10,fscal,fiz1);
1162             
1163             fjx0             = _mm_macc_pd(dx10,fscal,fjx0);
1164             fjy0             = _mm_macc_pd(dy10,fscal,fjy0);
1165             fjz0             = _mm_macc_pd(dz10,fscal,fjz0);
1166
1167             }
1168
1169             /**************************
1170              * CALCULATE INTERACTIONS *
1171              **************************/
1172
1173             if (gmx_mm_any_lt(rsq20,rcutoff2))
1174             {
1175
1176             r20              = _mm_mul_pd(rsq20,rinv20);
1177
1178             /* Compute parameters for interactions between i and j atoms */
1179             qq20             = _mm_mul_pd(iq2,jq0);
1180
1181             /* EWALD ELECTROSTATICS */
1182
1183             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
1184             ewrt             = _mm_mul_pd(r20,ewtabscale);
1185             ewitab           = _mm_cvttpd_epi32(ewrt);
1186 #ifdef __XOP__
1187             eweps            = _mm_frcz_pd(ewrt);
1188 #else
1189             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
1190 #endif
1191             twoeweps         = _mm_add_pd(eweps,eweps);
1192             ewitab           = _mm_slli_epi32(ewitab,2);
1193             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
1194             ewtabD           = _mm_setzero_pd();
1195             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
1196             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
1197             ewtabFn          = _mm_setzero_pd();
1198             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
1199             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
1200             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
1201             velec            = _mm_mul_pd(qq20,_mm_sub_pd(rinv20,velec));
1202             felec            = _mm_mul_pd(_mm_mul_pd(qq20,rinv20),_mm_sub_pd(rinvsq20,felec));
1203
1204             d                = _mm_sub_pd(r20,rswitch);
1205             d                = _mm_max_pd(d,_mm_setzero_pd());
1206             d2               = _mm_mul_pd(d,d);
1207             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
1208
1209             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
1210
1211             /* Evaluate switch function */
1212             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
1213             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv20,_mm_mul_pd(velec,dsw)) );
1214             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
1215
1216             fscal            = felec;
1217
1218             fscal            = _mm_and_pd(fscal,cutoff_mask);
1219
1220             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
1221
1222             /* Update vectorial force */
1223             fix2             = _mm_macc_pd(dx20,fscal,fix2);
1224             fiy2             = _mm_macc_pd(dy20,fscal,fiy2);
1225             fiz2             = _mm_macc_pd(dz20,fscal,fiz2);
1226             
1227             fjx0             = _mm_macc_pd(dx20,fscal,fjx0);
1228             fjy0             = _mm_macc_pd(dy20,fscal,fjy0);
1229             fjz0             = _mm_macc_pd(dz20,fscal,fjz0);
1230
1231             }
1232
1233             /**************************
1234              * CALCULATE INTERACTIONS *
1235              **************************/
1236
1237             if (gmx_mm_any_lt(rsq30,rcutoff2))
1238             {
1239
1240             r30              = _mm_mul_pd(rsq30,rinv30);
1241
1242             /* Compute parameters for interactions between i and j atoms */
1243             qq30             = _mm_mul_pd(iq3,jq0);
1244
1245             /* EWALD ELECTROSTATICS */
1246
1247             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
1248             ewrt             = _mm_mul_pd(r30,ewtabscale);
1249             ewitab           = _mm_cvttpd_epi32(ewrt);
1250 #ifdef __XOP__
1251             eweps            = _mm_frcz_pd(ewrt);
1252 #else
1253             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
1254 #endif
1255             twoeweps         = _mm_add_pd(eweps,eweps);
1256             ewitab           = _mm_slli_epi32(ewitab,2);
1257             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
1258             ewtabD           = _mm_setzero_pd();
1259             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
1260             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
1261             ewtabFn          = _mm_setzero_pd();
1262             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
1263             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
1264             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
1265             velec            = _mm_mul_pd(qq30,_mm_sub_pd(rinv30,velec));
1266             felec            = _mm_mul_pd(_mm_mul_pd(qq30,rinv30),_mm_sub_pd(rinvsq30,felec));
1267
1268             d                = _mm_sub_pd(r30,rswitch);
1269             d                = _mm_max_pd(d,_mm_setzero_pd());
1270             d2               = _mm_mul_pd(d,d);
1271             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_macc_pd(d,_mm_macc_pd(d,swV5,swV4),swV3))));
1272
1273             dsw              = _mm_mul_pd(d2,_mm_macc_pd(d,_mm_macc_pd(d,swF4,swF3),swF2));
1274
1275             /* Evaluate switch function */
1276             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
1277             felec            = _mm_msub_pd( felec,sw , _mm_mul_pd(rinv30,_mm_mul_pd(velec,dsw)) );
1278             cutoff_mask      = _mm_cmplt_pd(rsq30,rcutoff2);
1279
1280             fscal            = felec;
1281
1282             fscal            = _mm_and_pd(fscal,cutoff_mask);
1283
1284             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
1285
1286             /* Update vectorial force */
1287             fix3             = _mm_macc_pd(dx30,fscal,fix3);
1288             fiy3             = _mm_macc_pd(dy30,fscal,fiy3);
1289             fiz3             = _mm_macc_pd(dz30,fscal,fiz3);
1290             
1291             fjx0             = _mm_macc_pd(dx30,fscal,fjx0);
1292             fjy0             = _mm_macc_pd(dy30,fscal,fjy0);
1293             fjz0             = _mm_macc_pd(dz30,fscal,fjz0);
1294
1295             }
1296
1297             gmx_mm_decrement_1rvec_1ptr_swizzle_pd(f+j_coord_offsetA,fjx0,fjy0,fjz0);
1298
1299             /* Inner loop uses 198 flops */
1300         }
1301
1302         /* End of innermost loop */
1303
1304         gmx_mm_update_iforce_3atom_swizzle_pd(fix1,fiy1,fiz1,fix2,fiy2,fiz2,fix3,fiy3,fiz3,
1305                                               f+i_coord_offset+DIM,fshift+i_shift_offset);
1306
1307         /* Increment number of inner iterations */
1308         inneriter                  += j_index_end - j_index_start;
1309
1310         /* Outer loop uses 18 flops */
1311     }
1312
1313     /* Increment number of outer iterations */
1314     outeriter        += nri;
1315
1316     /* Update outer/inner flops */
1317
1318     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_W4_F,outeriter*18 + inneriter*198);
1319 }