Remove all unnecessary HAVE_CONFIG_H
[alexxy/gromacs.git] / src / gromacs / gmxlib / nonbonded / nb_kernel_avx_128_fma_double / nb_kernel_ElecEwSh_VdwNone_GeomW4P1_avx_128_fma_double.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*
36  * Note: this file was generated by the GROMACS avx_128_fma_double kernel generator.
37  */
38 #include "config.h"
39
40 #include <math.h>
41
42 #include "../nb_kernel.h"
43 #include "types/simple.h"
44 #include "gromacs/math/vec.h"
45 #include "nrnb.h"
46
47 #include "gromacs/simd/math_x86_avx_128_fma_double.h"
48 #include "kernelutil_x86_avx_128_fma_double.h"
49
50 /*
51  * Gromacs nonbonded kernel:   nb_kernel_ElecEwSh_VdwNone_GeomW4P1_VF_avx_128_fma_double
52  * Electrostatics interaction: Ewald
53  * VdW interaction:            None
54  * Geometry:                   Water4-Particle
55  * Calculate force/pot:        PotentialAndForce
56  */
57 void
58 nb_kernel_ElecEwSh_VdwNone_GeomW4P1_VF_avx_128_fma_double
59                     (t_nblist                    * gmx_restrict       nlist,
60                      rvec                        * gmx_restrict          xx,
61                      rvec                        * gmx_restrict          ff,
62                      t_forcerec                  * gmx_restrict          fr,
63                      t_mdatoms                   * gmx_restrict     mdatoms,
64                      nb_kernel_data_t gmx_unused * gmx_restrict kernel_data,
65                      t_nrnb                      * gmx_restrict        nrnb)
66 {
67     /* Suffixes 0,1,2,3 refer to particle indices for waters in the inner or outer loop, or
68      * just 0 for non-waters.
69      * Suffixes A,B refer to j loop unrolling done with SSE double precision, e.g. for the two 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;
75     int              j_coord_offsetA,j_coord_offsetB;
76     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
77     real             rcutoff_scalar;
78     real             *shiftvec,*fshift,*x,*f;
79     __m128d          tx,ty,tz,fscal,rcutoff,rcutoff2,jidxall;
80     int              vdwioffset1;
81     __m128d          ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
82     int              vdwioffset2;
83     __m128d          ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
84     int              vdwioffset3;
85     __m128d          ix3,iy3,iz3,fix3,fiy3,fiz3,iq3,isai3;
86     int              vdwjidx0A,vdwjidx0B;
87     __m128d          jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
88     __m128d          dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10;
89     __m128d          dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20;
90     __m128d          dx30,dy30,dz30,rsq30,rinv30,rinvsq30,r30,qq30,c6_30,c12_30;
91     __m128d          velec,felec,velecsum,facel,crf,krf,krf2;
92     real             *charge;
93     __m128i          ewitab;
94     __m128d          ewtabscale,eweps,twoeweps,sh_ewald,ewrt,ewtabhalfspace,ewtabF,ewtabFn,ewtabD,ewtabV;
95     real             *ewtab;
96     __m128d          dummy_mask,cutoff_mask;
97     __m128d          signbit   = gmx_mm_castsi128_pd( _mm_set_epi32(0x80000000,0x00000000,0x80000000,0x00000000) );
98     __m128d          one     = _mm_set1_pd(1.0);
99     __m128d          two     = _mm_set1_pd(2.0);
100     x                = xx[0];
101     f                = ff[0];
102
103     nri              = nlist->nri;
104     iinr             = nlist->iinr;
105     jindex           = nlist->jindex;
106     jjnr             = nlist->jjnr;
107     shiftidx         = nlist->shift;
108     gid              = nlist->gid;
109     shiftvec         = fr->shift_vec[0];
110     fshift           = fr->fshift[0];
111     facel            = _mm_set1_pd(fr->epsfac);
112     charge           = mdatoms->chargeA;
113
114     sh_ewald         = _mm_set1_pd(fr->ic->sh_ewald);
115     ewtab            = fr->ic->tabq_coul_FDV0;
116     ewtabscale       = _mm_set1_pd(fr->ic->tabq_scale);
117     ewtabhalfspace   = _mm_set1_pd(0.5/fr->ic->tabq_scale);
118
119     /* Setup water-specific parameters */
120     inr              = nlist->iinr[0];
121     iq1              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+1]));
122     iq2              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+2]));
123     iq3              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+3]));
124
125     /* When we use explicit cutoffs the value must be identical for elec and VdW, so use elec as an arbitrary choice */
126     rcutoff_scalar   = fr->rcoulomb;
127     rcutoff          = _mm_set1_pd(rcutoff_scalar);
128     rcutoff2         = _mm_mul_pd(rcutoff,rcutoff);
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(_mm_sub_pd(rinv10,sh_ewald),velec));
247             felec            = _mm_mul_pd(_mm_mul_pd(qq10,rinv10),_mm_sub_pd(rinvsq10,felec));
248
249             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
250
251             /* Update potential sum for this i atom from the interaction with this j atom. */
252             velec            = _mm_and_pd(velec,cutoff_mask);
253             velecsum         = _mm_add_pd(velecsum,velec);
254
255             fscal            = felec;
256
257             fscal            = _mm_and_pd(fscal,cutoff_mask);
258
259             /* Update vectorial force */
260             fix1             = _mm_macc_pd(dx10,fscal,fix1);
261             fiy1             = _mm_macc_pd(dy10,fscal,fiy1);
262             fiz1             = _mm_macc_pd(dz10,fscal,fiz1);
263             
264             fjx0             = _mm_macc_pd(dx10,fscal,fjx0);
265             fjy0             = _mm_macc_pd(dy10,fscal,fjy0);
266             fjz0             = _mm_macc_pd(dz10,fscal,fjz0);
267
268             }
269
270             /**************************
271              * CALCULATE INTERACTIONS *
272              **************************/
273
274             if (gmx_mm_any_lt(rsq20,rcutoff2))
275             {
276
277             r20              = _mm_mul_pd(rsq20,rinv20);
278
279             /* Compute parameters for interactions between i and j atoms */
280             qq20             = _mm_mul_pd(iq2,jq0);
281
282             /* EWALD ELECTROSTATICS */
283
284             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
285             ewrt             = _mm_mul_pd(r20,ewtabscale);
286             ewitab           = _mm_cvttpd_epi32(ewrt);
287 #ifdef __XOP__
288             eweps            = _mm_frcz_pd(ewrt);
289 #else
290             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
291 #endif
292             twoeweps         = _mm_add_pd(eweps,eweps);
293             ewitab           = _mm_slli_epi32(ewitab,2);
294             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
295             ewtabD           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,1) );
296             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
297             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
298             ewtabFn          = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,1) +2);
299             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
300             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
301             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
302             velec            = _mm_mul_pd(qq20,_mm_sub_pd(_mm_sub_pd(rinv20,sh_ewald),velec));
303             felec            = _mm_mul_pd(_mm_mul_pd(qq20,rinv20),_mm_sub_pd(rinvsq20,felec));
304
305             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
306
307             /* Update potential sum for this i atom from the interaction with this j atom. */
308             velec            = _mm_and_pd(velec,cutoff_mask);
309             velecsum         = _mm_add_pd(velecsum,velec);
310
311             fscal            = felec;
312
313             fscal            = _mm_and_pd(fscal,cutoff_mask);
314
315             /* Update vectorial force */
316             fix2             = _mm_macc_pd(dx20,fscal,fix2);
317             fiy2             = _mm_macc_pd(dy20,fscal,fiy2);
318             fiz2             = _mm_macc_pd(dz20,fscal,fiz2);
319             
320             fjx0             = _mm_macc_pd(dx20,fscal,fjx0);
321             fjy0             = _mm_macc_pd(dy20,fscal,fjy0);
322             fjz0             = _mm_macc_pd(dz20,fscal,fjz0);
323
324             }
325
326             /**************************
327              * CALCULATE INTERACTIONS *
328              **************************/
329
330             if (gmx_mm_any_lt(rsq30,rcutoff2))
331             {
332
333             r30              = _mm_mul_pd(rsq30,rinv30);
334
335             /* Compute parameters for interactions between i and j atoms */
336             qq30             = _mm_mul_pd(iq3,jq0);
337
338             /* EWALD ELECTROSTATICS */
339
340             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
341             ewrt             = _mm_mul_pd(r30,ewtabscale);
342             ewitab           = _mm_cvttpd_epi32(ewrt);
343 #ifdef __XOP__
344             eweps            = _mm_frcz_pd(ewrt);
345 #else
346             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
347 #endif
348             twoeweps         = _mm_add_pd(eweps,eweps);
349             ewitab           = _mm_slli_epi32(ewitab,2);
350             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
351             ewtabD           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,1) );
352             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
353             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
354             ewtabFn          = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,1) +2);
355             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
356             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
357             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
358             velec            = _mm_mul_pd(qq30,_mm_sub_pd(_mm_sub_pd(rinv30,sh_ewald),velec));
359             felec            = _mm_mul_pd(_mm_mul_pd(qq30,rinv30),_mm_sub_pd(rinvsq30,felec));
360
361             cutoff_mask      = _mm_cmplt_pd(rsq30,rcutoff2);
362
363             /* Update potential sum for this i atom from the interaction with this j atom. */
364             velec            = _mm_and_pd(velec,cutoff_mask);
365             velecsum         = _mm_add_pd(velecsum,velec);
366
367             fscal            = felec;
368
369             fscal            = _mm_and_pd(fscal,cutoff_mask);
370
371             /* Update vectorial force */
372             fix3             = _mm_macc_pd(dx30,fscal,fix3);
373             fiy3             = _mm_macc_pd(dy30,fscal,fiy3);
374             fiz3             = _mm_macc_pd(dz30,fscal,fiz3);
375             
376             fjx0             = _mm_macc_pd(dx30,fscal,fjx0);
377             fjy0             = _mm_macc_pd(dy30,fscal,fjy0);
378             fjz0             = _mm_macc_pd(dz30,fscal,fjz0);
379
380             }
381
382             gmx_mm_decrement_1rvec_2ptr_swizzle_pd(f+j_coord_offsetA,f+j_coord_offsetB,fjx0,fjy0,fjz0);
383
384             /* Inner loop uses 150 flops */
385         }
386
387         if(jidx<j_index_end)
388         {
389
390             jnrA             = jjnr[jidx];
391             j_coord_offsetA  = DIM*jnrA;
392
393             /* load j atom coordinates */
394             gmx_mm_load_1rvec_1ptr_swizzle_pd(x+j_coord_offsetA,
395                                               &jx0,&jy0,&jz0);
396
397             /* Calculate displacement vector */
398             dx10             = _mm_sub_pd(ix1,jx0);
399             dy10             = _mm_sub_pd(iy1,jy0);
400             dz10             = _mm_sub_pd(iz1,jz0);
401             dx20             = _mm_sub_pd(ix2,jx0);
402             dy20             = _mm_sub_pd(iy2,jy0);
403             dz20             = _mm_sub_pd(iz2,jz0);
404             dx30             = _mm_sub_pd(ix3,jx0);
405             dy30             = _mm_sub_pd(iy3,jy0);
406             dz30             = _mm_sub_pd(iz3,jz0);
407
408             /* Calculate squared distance and things based on it */
409             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
410             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
411             rsq30            = gmx_mm_calc_rsq_pd(dx30,dy30,dz30);
412
413             rinv10           = gmx_mm_invsqrt_pd(rsq10);
414             rinv20           = gmx_mm_invsqrt_pd(rsq20);
415             rinv30           = gmx_mm_invsqrt_pd(rsq30);
416
417             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
418             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
419             rinvsq30         = _mm_mul_pd(rinv30,rinv30);
420
421             /* Load parameters for j particles */
422             jq0              = _mm_load_sd(charge+jnrA+0);
423
424             fjx0             = _mm_setzero_pd();
425             fjy0             = _mm_setzero_pd();
426             fjz0             = _mm_setzero_pd();
427
428             /**************************
429              * CALCULATE INTERACTIONS *
430              **************************/
431
432             if (gmx_mm_any_lt(rsq10,rcutoff2))
433             {
434
435             r10              = _mm_mul_pd(rsq10,rinv10);
436
437             /* Compute parameters for interactions between i and j atoms */
438             qq10             = _mm_mul_pd(iq1,jq0);
439
440             /* EWALD ELECTROSTATICS */
441
442             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
443             ewrt             = _mm_mul_pd(r10,ewtabscale);
444             ewitab           = _mm_cvttpd_epi32(ewrt);
445 #ifdef __XOP__
446             eweps            = _mm_frcz_pd(ewrt);
447 #else
448             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
449 #endif
450             twoeweps         = _mm_add_pd(eweps,eweps);
451             ewitab           = _mm_slli_epi32(ewitab,2);
452             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
453             ewtabD           = _mm_setzero_pd();
454             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
455             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
456             ewtabFn          = _mm_setzero_pd();
457             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
458             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
459             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
460             velec            = _mm_mul_pd(qq10,_mm_sub_pd(_mm_sub_pd(rinv10,sh_ewald),velec));
461             felec            = _mm_mul_pd(_mm_mul_pd(qq10,rinv10),_mm_sub_pd(rinvsq10,felec));
462
463             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
464
465             /* Update potential sum for this i atom from the interaction with this j atom. */
466             velec            = _mm_and_pd(velec,cutoff_mask);
467             velec            = _mm_unpacklo_pd(velec,_mm_setzero_pd());
468             velecsum         = _mm_add_pd(velecsum,velec);
469
470             fscal            = felec;
471
472             fscal            = _mm_and_pd(fscal,cutoff_mask);
473
474             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
475
476             /* Update vectorial force */
477             fix1             = _mm_macc_pd(dx10,fscal,fix1);
478             fiy1             = _mm_macc_pd(dy10,fscal,fiy1);
479             fiz1             = _mm_macc_pd(dz10,fscal,fiz1);
480             
481             fjx0             = _mm_macc_pd(dx10,fscal,fjx0);
482             fjy0             = _mm_macc_pd(dy10,fscal,fjy0);
483             fjz0             = _mm_macc_pd(dz10,fscal,fjz0);
484
485             }
486
487             /**************************
488              * CALCULATE INTERACTIONS *
489              **************************/
490
491             if (gmx_mm_any_lt(rsq20,rcutoff2))
492             {
493
494             r20              = _mm_mul_pd(rsq20,rinv20);
495
496             /* Compute parameters for interactions between i and j atoms */
497             qq20             = _mm_mul_pd(iq2,jq0);
498
499             /* EWALD ELECTROSTATICS */
500
501             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
502             ewrt             = _mm_mul_pd(r20,ewtabscale);
503             ewitab           = _mm_cvttpd_epi32(ewrt);
504 #ifdef __XOP__
505             eweps            = _mm_frcz_pd(ewrt);
506 #else
507             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
508 #endif
509             twoeweps         = _mm_add_pd(eweps,eweps);
510             ewitab           = _mm_slli_epi32(ewitab,2);
511             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
512             ewtabD           = _mm_setzero_pd();
513             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
514             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
515             ewtabFn          = _mm_setzero_pd();
516             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
517             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
518             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
519             velec            = _mm_mul_pd(qq20,_mm_sub_pd(_mm_sub_pd(rinv20,sh_ewald),velec));
520             felec            = _mm_mul_pd(_mm_mul_pd(qq20,rinv20),_mm_sub_pd(rinvsq20,felec));
521
522             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
523
524             /* Update potential sum for this i atom from the interaction with this j atom. */
525             velec            = _mm_and_pd(velec,cutoff_mask);
526             velec            = _mm_unpacklo_pd(velec,_mm_setzero_pd());
527             velecsum         = _mm_add_pd(velecsum,velec);
528
529             fscal            = felec;
530
531             fscal            = _mm_and_pd(fscal,cutoff_mask);
532
533             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
534
535             /* Update vectorial force */
536             fix2             = _mm_macc_pd(dx20,fscal,fix2);
537             fiy2             = _mm_macc_pd(dy20,fscal,fiy2);
538             fiz2             = _mm_macc_pd(dz20,fscal,fiz2);
539             
540             fjx0             = _mm_macc_pd(dx20,fscal,fjx0);
541             fjy0             = _mm_macc_pd(dy20,fscal,fjy0);
542             fjz0             = _mm_macc_pd(dz20,fscal,fjz0);
543
544             }
545
546             /**************************
547              * CALCULATE INTERACTIONS *
548              **************************/
549
550             if (gmx_mm_any_lt(rsq30,rcutoff2))
551             {
552
553             r30              = _mm_mul_pd(rsq30,rinv30);
554
555             /* Compute parameters for interactions between i and j atoms */
556             qq30             = _mm_mul_pd(iq3,jq0);
557
558             /* EWALD ELECTROSTATICS */
559
560             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
561             ewrt             = _mm_mul_pd(r30,ewtabscale);
562             ewitab           = _mm_cvttpd_epi32(ewrt);
563 #ifdef __XOP__
564             eweps            = _mm_frcz_pd(ewrt);
565 #else
566             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
567 #endif
568             twoeweps         = _mm_add_pd(eweps,eweps);
569             ewitab           = _mm_slli_epi32(ewitab,2);
570             ewtabF           = _mm_load_pd( ewtab + _mm_extract_epi32(ewitab,0) );
571             ewtabD           = _mm_setzero_pd();
572             GMX_MM_TRANSPOSE2_PD(ewtabF,ewtabD);
573             ewtabV           = _mm_load_sd( ewtab + _mm_extract_epi32(ewitab,0) +2);
574             ewtabFn          = _mm_setzero_pd();
575             GMX_MM_TRANSPOSE2_PD(ewtabV,ewtabFn);
576             felec            = _mm_macc_pd(eweps,ewtabD,ewtabF);
577             velec            = _mm_nmacc_pd(_mm_mul_pd(ewtabhalfspace,eweps) ,_mm_add_pd(ewtabF,felec), ewtabV);
578             velec            = _mm_mul_pd(qq30,_mm_sub_pd(_mm_sub_pd(rinv30,sh_ewald),velec));
579             felec            = _mm_mul_pd(_mm_mul_pd(qq30,rinv30),_mm_sub_pd(rinvsq30,felec));
580
581             cutoff_mask      = _mm_cmplt_pd(rsq30,rcutoff2);
582
583             /* Update potential sum for this i atom from the interaction with this j atom. */
584             velec            = _mm_and_pd(velec,cutoff_mask);
585             velec            = _mm_unpacklo_pd(velec,_mm_setzero_pd());
586             velecsum         = _mm_add_pd(velecsum,velec);
587
588             fscal            = felec;
589
590             fscal            = _mm_and_pd(fscal,cutoff_mask);
591
592             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
593
594             /* Update vectorial force */
595             fix3             = _mm_macc_pd(dx30,fscal,fix3);
596             fiy3             = _mm_macc_pd(dy30,fscal,fiy3);
597             fiz3             = _mm_macc_pd(dz30,fscal,fiz3);
598             
599             fjx0             = _mm_macc_pd(dx30,fscal,fjx0);
600             fjy0             = _mm_macc_pd(dy30,fscal,fjy0);
601             fjz0             = _mm_macc_pd(dz30,fscal,fjz0);
602
603             }
604
605             gmx_mm_decrement_1rvec_1ptr_swizzle_pd(f+j_coord_offsetA,fjx0,fjy0,fjz0);
606
607             /* Inner loop uses 150 flops */
608         }
609
610         /* End of innermost loop */
611
612         gmx_mm_update_iforce_3atom_swizzle_pd(fix1,fiy1,fiz1,fix2,fiy2,fiz2,fix3,fiy3,fiz3,
613                                               f+i_coord_offset+DIM,fshift+i_shift_offset);
614
615         ggid                        = gid[iidx];
616         /* Update potential energies */
617         gmx_mm_update_1pot_pd(velecsum,kernel_data->energygrp_elec+ggid);
618
619         /* Increment number of inner iterations */
620         inneriter                  += j_index_end - j_index_start;
621
622         /* Outer loop uses 19 flops */
623     }
624
625     /* Increment number of outer iterations */
626     outeriter        += nri;
627
628     /* Update outer/inner flops */
629
630     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_W4_VF,outeriter*19 + inneriter*150);
631 }
632 /*
633  * Gromacs nonbonded kernel:   nb_kernel_ElecEwSh_VdwNone_GeomW4P1_F_avx_128_fma_double
634  * Electrostatics interaction: Ewald
635  * VdW interaction:            None
636  * Geometry:                   Water4-Particle
637  * Calculate force/pot:        Force
638  */
639 void
640 nb_kernel_ElecEwSh_VdwNone_GeomW4P1_F_avx_128_fma_double
641                     (t_nblist                    * gmx_restrict       nlist,
642                      rvec                        * gmx_restrict          xx,
643                      rvec                        * gmx_restrict          ff,
644                      t_forcerec                  * gmx_restrict          fr,
645                      t_mdatoms                   * gmx_restrict     mdatoms,
646                      nb_kernel_data_t gmx_unused * gmx_restrict kernel_data,
647                      t_nrnb                      * gmx_restrict        nrnb)
648 {
649     /* Suffixes 0,1,2,3 refer to particle indices for waters in the inner or outer loop, or
650      * just 0 for non-waters.
651      * Suffixes A,B refer to j loop unrolling done with SSE double precision, e.g. for the two different
652      * jnr indices corresponding to data put in the four positions in the SIMD register.
653      */
654     int              i_shift_offset,i_coord_offset,outeriter,inneriter;
655     int              j_index_start,j_index_end,jidx,nri,inr,ggid,iidx;
656     int              jnrA,jnrB;
657     int              j_coord_offsetA,j_coord_offsetB;
658     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
659     real             rcutoff_scalar;
660     real             *shiftvec,*fshift,*x,*f;
661     __m128d          tx,ty,tz,fscal,rcutoff,rcutoff2,jidxall;
662     int              vdwioffset1;
663     __m128d          ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
664     int              vdwioffset2;
665     __m128d          ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
666     int              vdwioffset3;
667     __m128d          ix3,iy3,iz3,fix3,fiy3,fiz3,iq3,isai3;
668     int              vdwjidx0A,vdwjidx0B;
669     __m128d          jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
670     __m128d          dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10;
671     __m128d          dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20;
672     __m128d          dx30,dy30,dz30,rsq30,rinv30,rinvsq30,r30,qq30,c6_30,c12_30;
673     __m128d          velec,felec,velecsum,facel,crf,krf,krf2;
674     real             *charge;
675     __m128i          ewitab;
676     __m128d          ewtabscale,eweps,twoeweps,sh_ewald,ewrt,ewtabhalfspace,ewtabF,ewtabFn,ewtabD,ewtabV;
677     real             *ewtab;
678     __m128d          dummy_mask,cutoff_mask;
679     __m128d          signbit   = gmx_mm_castsi128_pd( _mm_set_epi32(0x80000000,0x00000000,0x80000000,0x00000000) );
680     __m128d          one     = _mm_set1_pd(1.0);
681     __m128d          two     = _mm_set1_pd(2.0);
682     x                = xx[0];
683     f                = ff[0];
684
685     nri              = nlist->nri;
686     iinr             = nlist->iinr;
687     jindex           = nlist->jindex;
688     jjnr             = nlist->jjnr;
689     shiftidx         = nlist->shift;
690     gid              = nlist->gid;
691     shiftvec         = fr->shift_vec[0];
692     fshift           = fr->fshift[0];
693     facel            = _mm_set1_pd(fr->epsfac);
694     charge           = mdatoms->chargeA;
695
696     sh_ewald         = _mm_set1_pd(fr->ic->sh_ewald);
697     ewtab            = fr->ic->tabq_coul_F;
698     ewtabscale       = _mm_set1_pd(fr->ic->tabq_scale);
699     ewtabhalfspace   = _mm_set1_pd(0.5/fr->ic->tabq_scale);
700
701     /* Setup water-specific parameters */
702     inr              = nlist->iinr[0];
703     iq1              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+1]));
704     iq2              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+2]));
705     iq3              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+3]));
706
707     /* When we use explicit cutoffs the value must be identical for elec and VdW, so use elec as an arbitrary choice */
708     rcutoff_scalar   = fr->rcoulomb;
709     rcutoff          = _mm_set1_pd(rcutoff_scalar);
710     rcutoff2         = _mm_mul_pd(rcutoff,rcutoff);
711
712     /* Avoid stupid compiler warnings */
713     jnrA = jnrB = 0;
714     j_coord_offsetA = 0;
715     j_coord_offsetB = 0;
716
717     outeriter        = 0;
718     inneriter        = 0;
719
720     /* Start outer loop over neighborlists */
721     for(iidx=0; iidx<nri; iidx++)
722     {
723         /* Load shift vector for this list */
724         i_shift_offset   = DIM*shiftidx[iidx];
725
726         /* Load limits for loop over neighbors */
727         j_index_start    = jindex[iidx];
728         j_index_end      = jindex[iidx+1];
729
730         /* Get outer coordinate index */
731         inr              = iinr[iidx];
732         i_coord_offset   = DIM*inr;
733
734         /* Load i particle coords and add shift vector */
735         gmx_mm_load_shift_and_3rvec_broadcast_pd(shiftvec+i_shift_offset,x+i_coord_offset+DIM,
736                                                  &ix1,&iy1,&iz1,&ix2,&iy2,&iz2,&ix3,&iy3,&iz3);
737
738         fix1             = _mm_setzero_pd();
739         fiy1             = _mm_setzero_pd();
740         fiz1             = _mm_setzero_pd();
741         fix2             = _mm_setzero_pd();
742         fiy2             = _mm_setzero_pd();
743         fiz2             = _mm_setzero_pd();
744         fix3             = _mm_setzero_pd();
745         fiy3             = _mm_setzero_pd();
746         fiz3             = _mm_setzero_pd();
747
748         /* Start inner kernel loop */
749         for(jidx=j_index_start; jidx<j_index_end-1; jidx+=2)
750         {
751
752             /* Get j neighbor index, and coordinate index */
753             jnrA             = jjnr[jidx];
754             jnrB             = jjnr[jidx+1];
755             j_coord_offsetA  = DIM*jnrA;
756             j_coord_offsetB  = DIM*jnrB;
757
758             /* load j atom coordinates */
759             gmx_mm_load_1rvec_2ptr_swizzle_pd(x+j_coord_offsetA,x+j_coord_offsetB,
760                                               &jx0,&jy0,&jz0);
761
762             /* Calculate displacement vector */
763             dx10             = _mm_sub_pd(ix1,jx0);
764             dy10             = _mm_sub_pd(iy1,jy0);
765             dz10             = _mm_sub_pd(iz1,jz0);
766             dx20             = _mm_sub_pd(ix2,jx0);
767             dy20             = _mm_sub_pd(iy2,jy0);
768             dz20             = _mm_sub_pd(iz2,jz0);
769             dx30             = _mm_sub_pd(ix3,jx0);
770             dy30             = _mm_sub_pd(iy3,jy0);
771             dz30             = _mm_sub_pd(iz3,jz0);
772
773             /* Calculate squared distance and things based on it */
774             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
775             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
776             rsq30            = gmx_mm_calc_rsq_pd(dx30,dy30,dz30);
777
778             rinv10           = gmx_mm_invsqrt_pd(rsq10);
779             rinv20           = gmx_mm_invsqrt_pd(rsq20);
780             rinv30           = gmx_mm_invsqrt_pd(rsq30);
781
782             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
783             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
784             rinvsq30         = _mm_mul_pd(rinv30,rinv30);
785
786             /* Load parameters for j particles */
787             jq0              = gmx_mm_load_2real_swizzle_pd(charge+jnrA+0,charge+jnrB+0);
788
789             fjx0             = _mm_setzero_pd();
790             fjy0             = _mm_setzero_pd();
791             fjz0             = _mm_setzero_pd();
792
793             /**************************
794              * CALCULATE INTERACTIONS *
795              **************************/
796
797             if (gmx_mm_any_lt(rsq10,rcutoff2))
798             {
799
800             r10              = _mm_mul_pd(rsq10,rinv10);
801
802             /* Compute parameters for interactions between i and j atoms */
803             qq10             = _mm_mul_pd(iq1,jq0);
804
805             /* EWALD ELECTROSTATICS */
806
807             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
808             ewrt             = _mm_mul_pd(r10,ewtabscale);
809             ewitab           = _mm_cvttpd_epi32(ewrt);
810 #ifdef __XOP__
811             eweps            = _mm_frcz_pd(ewrt);
812 #else
813             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
814 #endif
815             twoeweps         = _mm_add_pd(eweps,eweps);
816             gmx_mm_load_2pair_swizzle_pd(ewtab+_mm_extract_epi32(ewitab,0),ewtab+_mm_extract_epi32(ewitab,1),
817                                          &ewtabF,&ewtabFn);
818             felec            = _mm_macc_pd(eweps,ewtabFn,_mm_mul_pd( _mm_sub_pd(one,eweps),ewtabF));
819             felec            = _mm_mul_pd(_mm_mul_pd(qq10,rinv10),_mm_sub_pd(rinvsq10,felec));
820
821             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
822
823             fscal            = felec;
824
825             fscal            = _mm_and_pd(fscal,cutoff_mask);
826
827             /* Update vectorial force */
828             fix1             = _mm_macc_pd(dx10,fscal,fix1);
829             fiy1             = _mm_macc_pd(dy10,fscal,fiy1);
830             fiz1             = _mm_macc_pd(dz10,fscal,fiz1);
831             
832             fjx0             = _mm_macc_pd(dx10,fscal,fjx0);
833             fjy0             = _mm_macc_pd(dy10,fscal,fjy0);
834             fjz0             = _mm_macc_pd(dz10,fscal,fjz0);
835
836             }
837
838             /**************************
839              * CALCULATE INTERACTIONS *
840              **************************/
841
842             if (gmx_mm_any_lt(rsq20,rcutoff2))
843             {
844
845             r20              = _mm_mul_pd(rsq20,rinv20);
846
847             /* Compute parameters for interactions between i and j atoms */
848             qq20             = _mm_mul_pd(iq2,jq0);
849
850             /* EWALD ELECTROSTATICS */
851
852             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
853             ewrt             = _mm_mul_pd(r20,ewtabscale);
854             ewitab           = _mm_cvttpd_epi32(ewrt);
855 #ifdef __XOP__
856             eweps            = _mm_frcz_pd(ewrt);
857 #else
858             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
859 #endif
860             twoeweps         = _mm_add_pd(eweps,eweps);
861             gmx_mm_load_2pair_swizzle_pd(ewtab+_mm_extract_epi32(ewitab,0),ewtab+_mm_extract_epi32(ewitab,1),
862                                          &ewtabF,&ewtabFn);
863             felec            = _mm_macc_pd(eweps,ewtabFn,_mm_mul_pd( _mm_sub_pd(one,eweps),ewtabF));
864             felec            = _mm_mul_pd(_mm_mul_pd(qq20,rinv20),_mm_sub_pd(rinvsq20,felec));
865
866             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
867
868             fscal            = felec;
869
870             fscal            = _mm_and_pd(fscal,cutoff_mask);
871
872             /* Update vectorial force */
873             fix2             = _mm_macc_pd(dx20,fscal,fix2);
874             fiy2             = _mm_macc_pd(dy20,fscal,fiy2);
875             fiz2             = _mm_macc_pd(dz20,fscal,fiz2);
876             
877             fjx0             = _mm_macc_pd(dx20,fscal,fjx0);
878             fjy0             = _mm_macc_pd(dy20,fscal,fjy0);
879             fjz0             = _mm_macc_pd(dz20,fscal,fjz0);
880
881             }
882
883             /**************************
884              * CALCULATE INTERACTIONS *
885              **************************/
886
887             if (gmx_mm_any_lt(rsq30,rcutoff2))
888             {
889
890             r30              = _mm_mul_pd(rsq30,rinv30);
891
892             /* Compute parameters for interactions between i and j atoms */
893             qq30             = _mm_mul_pd(iq3,jq0);
894
895             /* EWALD ELECTROSTATICS */
896
897             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
898             ewrt             = _mm_mul_pd(r30,ewtabscale);
899             ewitab           = _mm_cvttpd_epi32(ewrt);
900 #ifdef __XOP__
901             eweps            = _mm_frcz_pd(ewrt);
902 #else
903             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
904 #endif
905             twoeweps         = _mm_add_pd(eweps,eweps);
906             gmx_mm_load_2pair_swizzle_pd(ewtab+_mm_extract_epi32(ewitab,0),ewtab+_mm_extract_epi32(ewitab,1),
907                                          &ewtabF,&ewtabFn);
908             felec            = _mm_macc_pd(eweps,ewtabFn,_mm_mul_pd( _mm_sub_pd(one,eweps),ewtabF));
909             felec            = _mm_mul_pd(_mm_mul_pd(qq30,rinv30),_mm_sub_pd(rinvsq30,felec));
910
911             cutoff_mask      = _mm_cmplt_pd(rsq30,rcutoff2);
912
913             fscal            = felec;
914
915             fscal            = _mm_and_pd(fscal,cutoff_mask);
916
917             /* Update vectorial force */
918             fix3             = _mm_macc_pd(dx30,fscal,fix3);
919             fiy3             = _mm_macc_pd(dy30,fscal,fiy3);
920             fiz3             = _mm_macc_pd(dz30,fscal,fiz3);
921             
922             fjx0             = _mm_macc_pd(dx30,fscal,fjx0);
923             fjy0             = _mm_macc_pd(dy30,fscal,fjy0);
924             fjz0             = _mm_macc_pd(dz30,fscal,fjz0);
925
926             }
927
928             gmx_mm_decrement_1rvec_2ptr_swizzle_pd(f+j_coord_offsetA,f+j_coord_offsetB,fjx0,fjy0,fjz0);
929
930             /* Inner loop uses 129 flops */
931         }
932
933         if(jidx<j_index_end)
934         {
935
936             jnrA             = jjnr[jidx];
937             j_coord_offsetA  = DIM*jnrA;
938
939             /* load j atom coordinates */
940             gmx_mm_load_1rvec_1ptr_swizzle_pd(x+j_coord_offsetA,
941                                               &jx0,&jy0,&jz0);
942
943             /* Calculate displacement vector */
944             dx10             = _mm_sub_pd(ix1,jx0);
945             dy10             = _mm_sub_pd(iy1,jy0);
946             dz10             = _mm_sub_pd(iz1,jz0);
947             dx20             = _mm_sub_pd(ix2,jx0);
948             dy20             = _mm_sub_pd(iy2,jy0);
949             dz20             = _mm_sub_pd(iz2,jz0);
950             dx30             = _mm_sub_pd(ix3,jx0);
951             dy30             = _mm_sub_pd(iy3,jy0);
952             dz30             = _mm_sub_pd(iz3,jz0);
953
954             /* Calculate squared distance and things based on it */
955             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
956             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
957             rsq30            = gmx_mm_calc_rsq_pd(dx30,dy30,dz30);
958
959             rinv10           = gmx_mm_invsqrt_pd(rsq10);
960             rinv20           = gmx_mm_invsqrt_pd(rsq20);
961             rinv30           = gmx_mm_invsqrt_pd(rsq30);
962
963             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
964             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
965             rinvsq30         = _mm_mul_pd(rinv30,rinv30);
966
967             /* Load parameters for j particles */
968             jq0              = _mm_load_sd(charge+jnrA+0);
969
970             fjx0             = _mm_setzero_pd();
971             fjy0             = _mm_setzero_pd();
972             fjz0             = _mm_setzero_pd();
973
974             /**************************
975              * CALCULATE INTERACTIONS *
976              **************************/
977
978             if (gmx_mm_any_lt(rsq10,rcutoff2))
979             {
980
981             r10              = _mm_mul_pd(rsq10,rinv10);
982
983             /* Compute parameters for interactions between i and j atoms */
984             qq10             = _mm_mul_pd(iq1,jq0);
985
986             /* EWALD ELECTROSTATICS */
987
988             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
989             ewrt             = _mm_mul_pd(r10,ewtabscale);
990             ewitab           = _mm_cvttpd_epi32(ewrt);
991 #ifdef __XOP__
992             eweps            = _mm_frcz_pd(ewrt);
993 #else
994             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
995 #endif
996             twoeweps         = _mm_add_pd(eweps,eweps);
997             gmx_mm_load_1pair_swizzle_pd(ewtab+_mm_extract_epi32(ewitab,0),&ewtabF,&ewtabFn);
998             felec            = _mm_macc_pd(eweps,ewtabFn,_mm_mul_pd( _mm_sub_pd(one,eweps),ewtabF));
999             felec            = _mm_mul_pd(_mm_mul_pd(qq10,rinv10),_mm_sub_pd(rinvsq10,felec));
1000
1001             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
1002
1003             fscal            = felec;
1004
1005             fscal            = _mm_and_pd(fscal,cutoff_mask);
1006
1007             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
1008
1009             /* Update vectorial force */
1010             fix1             = _mm_macc_pd(dx10,fscal,fix1);
1011             fiy1             = _mm_macc_pd(dy10,fscal,fiy1);
1012             fiz1             = _mm_macc_pd(dz10,fscal,fiz1);
1013             
1014             fjx0             = _mm_macc_pd(dx10,fscal,fjx0);
1015             fjy0             = _mm_macc_pd(dy10,fscal,fjy0);
1016             fjz0             = _mm_macc_pd(dz10,fscal,fjz0);
1017
1018             }
1019
1020             /**************************
1021              * CALCULATE INTERACTIONS *
1022              **************************/
1023
1024             if (gmx_mm_any_lt(rsq20,rcutoff2))
1025             {
1026
1027             r20              = _mm_mul_pd(rsq20,rinv20);
1028
1029             /* Compute parameters for interactions between i and j atoms */
1030             qq20             = _mm_mul_pd(iq2,jq0);
1031
1032             /* EWALD ELECTROSTATICS */
1033
1034             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
1035             ewrt             = _mm_mul_pd(r20,ewtabscale);
1036             ewitab           = _mm_cvttpd_epi32(ewrt);
1037 #ifdef __XOP__
1038             eweps            = _mm_frcz_pd(ewrt);
1039 #else
1040             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
1041 #endif
1042             twoeweps         = _mm_add_pd(eweps,eweps);
1043             gmx_mm_load_1pair_swizzle_pd(ewtab+_mm_extract_epi32(ewitab,0),&ewtabF,&ewtabFn);
1044             felec            = _mm_macc_pd(eweps,ewtabFn,_mm_mul_pd( _mm_sub_pd(one,eweps),ewtabF));
1045             felec            = _mm_mul_pd(_mm_mul_pd(qq20,rinv20),_mm_sub_pd(rinvsq20,felec));
1046
1047             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
1048
1049             fscal            = felec;
1050
1051             fscal            = _mm_and_pd(fscal,cutoff_mask);
1052
1053             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
1054
1055             /* Update vectorial force */
1056             fix2             = _mm_macc_pd(dx20,fscal,fix2);
1057             fiy2             = _mm_macc_pd(dy20,fscal,fiy2);
1058             fiz2             = _mm_macc_pd(dz20,fscal,fiz2);
1059             
1060             fjx0             = _mm_macc_pd(dx20,fscal,fjx0);
1061             fjy0             = _mm_macc_pd(dy20,fscal,fjy0);
1062             fjz0             = _mm_macc_pd(dz20,fscal,fjz0);
1063
1064             }
1065
1066             /**************************
1067              * CALCULATE INTERACTIONS *
1068              **************************/
1069
1070             if (gmx_mm_any_lt(rsq30,rcutoff2))
1071             {
1072
1073             r30              = _mm_mul_pd(rsq30,rinv30);
1074
1075             /* Compute parameters for interactions between i and j atoms */
1076             qq30             = _mm_mul_pd(iq3,jq0);
1077
1078             /* EWALD ELECTROSTATICS */
1079
1080             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
1081             ewrt             = _mm_mul_pd(r30,ewtabscale);
1082             ewitab           = _mm_cvttpd_epi32(ewrt);
1083 #ifdef __XOP__
1084             eweps            = _mm_frcz_pd(ewrt);
1085 #else
1086             eweps            = _mm_sub_pd(ewrt,_mm_round_pd(ewrt, _MM_FROUND_FLOOR));
1087 #endif
1088             twoeweps         = _mm_add_pd(eweps,eweps);
1089             gmx_mm_load_1pair_swizzle_pd(ewtab+_mm_extract_epi32(ewitab,0),&ewtabF,&ewtabFn);
1090             felec            = _mm_macc_pd(eweps,ewtabFn,_mm_mul_pd( _mm_sub_pd(one,eweps),ewtabF));
1091             felec            = _mm_mul_pd(_mm_mul_pd(qq30,rinv30),_mm_sub_pd(rinvsq30,felec));
1092
1093             cutoff_mask      = _mm_cmplt_pd(rsq30,rcutoff2);
1094
1095             fscal            = felec;
1096
1097             fscal            = _mm_and_pd(fscal,cutoff_mask);
1098
1099             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
1100
1101             /* Update vectorial force */
1102             fix3             = _mm_macc_pd(dx30,fscal,fix3);
1103             fiy3             = _mm_macc_pd(dy30,fscal,fiy3);
1104             fiz3             = _mm_macc_pd(dz30,fscal,fiz3);
1105             
1106             fjx0             = _mm_macc_pd(dx30,fscal,fjx0);
1107             fjy0             = _mm_macc_pd(dy30,fscal,fjy0);
1108             fjz0             = _mm_macc_pd(dz30,fscal,fjz0);
1109
1110             }
1111
1112             gmx_mm_decrement_1rvec_1ptr_swizzle_pd(f+j_coord_offsetA,fjx0,fjy0,fjz0);
1113
1114             /* Inner loop uses 129 flops */
1115         }
1116
1117         /* End of innermost loop */
1118
1119         gmx_mm_update_iforce_3atom_swizzle_pd(fix1,fiy1,fiz1,fix2,fiy2,fiz2,fix3,fiy3,fiz3,
1120                                               f+i_coord_offset+DIM,fshift+i_shift_offset);
1121
1122         /* Increment number of inner iterations */
1123         inneriter                  += j_index_end - j_index_start;
1124
1125         /* Outer loop uses 18 flops */
1126     }
1127
1128     /* Increment number of outer iterations */
1129     outeriter        += nri;
1130
1131     /* Update outer/inner flops */
1132
1133     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_W4_F,outeriter*18 + inneriter*129);
1134 }