Remove no-inline-max-size and suppress remark
[alexxy/gromacs.git] / src / gromacs / gmxlib / nonbonded / nb_kernel_sse2_double / nb_kernel_ElecRFCut_VdwLJSw_GeomW3P1_sse2_double.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2013, 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 sse2_double kernel generator.
37  */
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #include <math.h>
43
44 #include "../nb_kernel.h"
45 #include "types/simple.h"
46 #include "vec.h"
47 #include "nrnb.h"
48
49 #include "gromacs/simd/math_x86_sse2_double.h"
50 #include "kernelutil_x86_sse2_double.h"
51
52 /*
53  * Gromacs nonbonded kernel:   nb_kernel_ElecRFCut_VdwLJSw_GeomW3P1_VF_sse2_double
54  * Electrostatics interaction: ReactionField
55  * VdW interaction:            LennardJones
56  * Geometry:                   Water3-Particle
57  * Calculate force/pot:        PotentialAndForce
58  */
59 void
60 nb_kernel_ElecRFCut_VdwLJSw_GeomW3P1_VF_sse2_double
61                     (t_nblist                    * gmx_restrict       nlist,
62                      rvec                        * gmx_restrict          xx,
63                      rvec                        * gmx_restrict          ff,
64                      t_forcerec                  * gmx_restrict          fr,
65                      t_mdatoms                   * gmx_restrict     mdatoms,
66                      nb_kernel_data_t gmx_unused * gmx_restrict kernel_data,
67                      t_nrnb                      * gmx_restrict        nrnb)
68 {
69     /* Suffixes 0,1,2,3 refer to particle indices for waters in the inner or outer loop, or
70      * just 0 for non-waters.
71      * Suffixes A,B refer to j loop unrolling done with SSE double precision, e.g. for the two different
72      * jnr indices corresponding to data put in the four positions in the SIMD register.
73      */
74     int              i_shift_offset,i_coord_offset,outeriter,inneriter;
75     int              j_index_start,j_index_end,jidx,nri,inr,ggid,iidx;
76     int              jnrA,jnrB;
77     int              j_coord_offsetA,j_coord_offsetB;
78     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
79     real             rcutoff_scalar;
80     real             *shiftvec,*fshift,*x,*f;
81     __m128d          tx,ty,tz,fscal,rcutoff,rcutoff2,jidxall;
82     int              vdwioffset0;
83     __m128d          ix0,iy0,iz0,fix0,fiy0,fiz0,iq0,isai0;
84     int              vdwioffset1;
85     __m128d          ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
86     int              vdwioffset2;
87     __m128d          ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
88     int              vdwjidx0A,vdwjidx0B;
89     __m128d          jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
90     __m128d          dx00,dy00,dz00,rsq00,rinv00,rinvsq00,r00,qq00,c6_00,c12_00;
91     __m128d          dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10;
92     __m128d          dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20;
93     __m128d          velec,felec,velecsum,facel,crf,krf,krf2;
94     real             *charge;
95     int              nvdwtype;
96     __m128d          rinvsix,rvdw,vvdw,vvdw6,vvdw12,fvdw,fvdw6,fvdw12,vvdwsum,sh_vdw_invrcut6;
97     int              *vdwtype;
98     real             *vdwparam;
99     __m128d          one_sixth   = _mm_set1_pd(1.0/6.0);
100     __m128d          one_twelfth = _mm_set1_pd(1.0/12.0);
101     __m128d          rswitch,swV3,swV4,swV5,swF2,swF3,swF4,d,d2,sw,dsw;
102     real             rswitch_scalar,d_scalar;
103     __m128d          dummy_mask,cutoff_mask;
104     __m128d          signbit   = gmx_mm_castsi128_pd( _mm_set_epi32(0x80000000,0x00000000,0x80000000,0x00000000) );
105     __m128d          one     = _mm_set1_pd(1.0);
106     __m128d          two     = _mm_set1_pd(2.0);
107     x                = xx[0];
108     f                = ff[0];
109
110     nri              = nlist->nri;
111     iinr             = nlist->iinr;
112     jindex           = nlist->jindex;
113     jjnr             = nlist->jjnr;
114     shiftidx         = nlist->shift;
115     gid              = nlist->gid;
116     shiftvec         = fr->shift_vec[0];
117     fshift           = fr->fshift[0];
118     facel            = _mm_set1_pd(fr->epsfac);
119     charge           = mdatoms->chargeA;
120     krf              = _mm_set1_pd(fr->ic->k_rf);
121     krf2             = _mm_set1_pd(fr->ic->k_rf*2.0);
122     crf              = _mm_set1_pd(fr->ic->c_rf);
123     nvdwtype         = fr->ntype;
124     vdwparam         = fr->nbfp;
125     vdwtype          = mdatoms->typeA;
126
127     /* Setup water-specific parameters */
128     inr              = nlist->iinr[0];
129     iq0              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+0]));
130     iq1              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+1]));
131     iq2              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+2]));
132     vdwioffset0      = 2*nvdwtype*vdwtype[inr+0];
133
134     /* When we use explicit cutoffs the value must be identical for elec and VdW, so use elec as an arbitrary choice */
135     rcutoff_scalar   = fr->rcoulomb;
136     rcutoff          = _mm_set1_pd(rcutoff_scalar);
137     rcutoff2         = _mm_mul_pd(rcutoff,rcutoff);
138
139     rswitch_scalar   = fr->rvdw_switch;
140     rswitch          = _mm_set1_pd(rswitch_scalar);
141     /* Setup switch parameters */
142     d_scalar         = rcutoff_scalar-rswitch_scalar;
143     d                = _mm_set1_pd(d_scalar);
144     swV3             = _mm_set1_pd(-10.0/(d_scalar*d_scalar*d_scalar));
145     swV4             = _mm_set1_pd( 15.0/(d_scalar*d_scalar*d_scalar*d_scalar));
146     swV5             = _mm_set1_pd( -6.0/(d_scalar*d_scalar*d_scalar*d_scalar*d_scalar));
147     swF2             = _mm_set1_pd(-30.0/(d_scalar*d_scalar*d_scalar));
148     swF3             = _mm_set1_pd( 60.0/(d_scalar*d_scalar*d_scalar*d_scalar));
149     swF4             = _mm_set1_pd(-30.0/(d_scalar*d_scalar*d_scalar*d_scalar*d_scalar));
150
151     /* Avoid stupid compiler warnings */
152     jnrA = jnrB = 0;
153     j_coord_offsetA = 0;
154     j_coord_offsetB = 0;
155
156     outeriter        = 0;
157     inneriter        = 0;
158
159     /* Start outer loop over neighborlists */
160     for(iidx=0; iidx<nri; iidx++)
161     {
162         /* Load shift vector for this list */
163         i_shift_offset   = DIM*shiftidx[iidx];
164
165         /* Load limits for loop over neighbors */
166         j_index_start    = jindex[iidx];
167         j_index_end      = jindex[iidx+1];
168
169         /* Get outer coordinate index */
170         inr              = iinr[iidx];
171         i_coord_offset   = DIM*inr;
172
173         /* Load i particle coords and add shift vector */
174         gmx_mm_load_shift_and_3rvec_broadcast_pd(shiftvec+i_shift_offset,x+i_coord_offset,
175                                                  &ix0,&iy0,&iz0,&ix1,&iy1,&iz1,&ix2,&iy2,&iz2);
176
177         fix0             = _mm_setzero_pd();
178         fiy0             = _mm_setzero_pd();
179         fiz0             = _mm_setzero_pd();
180         fix1             = _mm_setzero_pd();
181         fiy1             = _mm_setzero_pd();
182         fiz1             = _mm_setzero_pd();
183         fix2             = _mm_setzero_pd();
184         fiy2             = _mm_setzero_pd();
185         fiz2             = _mm_setzero_pd();
186
187         /* Reset potential sums */
188         velecsum         = _mm_setzero_pd();
189         vvdwsum          = _mm_setzero_pd();
190
191         /* Start inner kernel loop */
192         for(jidx=j_index_start; jidx<j_index_end-1; jidx+=2)
193         {
194
195             /* Get j neighbor index, and coordinate index */
196             jnrA             = jjnr[jidx];
197             jnrB             = jjnr[jidx+1];
198             j_coord_offsetA  = DIM*jnrA;
199             j_coord_offsetB  = DIM*jnrB;
200
201             /* load j atom coordinates */
202             gmx_mm_load_1rvec_2ptr_swizzle_pd(x+j_coord_offsetA,x+j_coord_offsetB,
203                                               &jx0,&jy0,&jz0);
204
205             /* Calculate displacement vector */
206             dx00             = _mm_sub_pd(ix0,jx0);
207             dy00             = _mm_sub_pd(iy0,jy0);
208             dz00             = _mm_sub_pd(iz0,jz0);
209             dx10             = _mm_sub_pd(ix1,jx0);
210             dy10             = _mm_sub_pd(iy1,jy0);
211             dz10             = _mm_sub_pd(iz1,jz0);
212             dx20             = _mm_sub_pd(ix2,jx0);
213             dy20             = _mm_sub_pd(iy2,jy0);
214             dz20             = _mm_sub_pd(iz2,jz0);
215
216             /* Calculate squared distance and things based on it */
217             rsq00            = gmx_mm_calc_rsq_pd(dx00,dy00,dz00);
218             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
219             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
220
221             rinv00           = gmx_mm_invsqrt_pd(rsq00);
222             rinv10           = gmx_mm_invsqrt_pd(rsq10);
223             rinv20           = gmx_mm_invsqrt_pd(rsq20);
224
225             rinvsq00         = _mm_mul_pd(rinv00,rinv00);
226             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
227             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
228
229             /* Load parameters for j particles */
230             jq0              = gmx_mm_load_2real_swizzle_pd(charge+jnrA+0,charge+jnrB+0);
231             vdwjidx0A        = 2*vdwtype[jnrA+0];
232             vdwjidx0B        = 2*vdwtype[jnrB+0];
233
234             fjx0             = _mm_setzero_pd();
235             fjy0             = _mm_setzero_pd();
236             fjz0             = _mm_setzero_pd();
237
238             /**************************
239              * CALCULATE INTERACTIONS *
240              **************************/
241
242             if (gmx_mm_any_lt(rsq00,rcutoff2))
243             {
244
245             r00              = _mm_mul_pd(rsq00,rinv00);
246
247             /* Compute parameters for interactions between i and j atoms */
248             qq00             = _mm_mul_pd(iq0,jq0);
249             gmx_mm_load_2pair_swizzle_pd(vdwparam+vdwioffset0+vdwjidx0A,
250                                          vdwparam+vdwioffset0+vdwjidx0B,&c6_00,&c12_00);
251
252             /* REACTION-FIELD ELECTROSTATICS */
253             velec            = _mm_mul_pd(qq00,_mm_sub_pd(_mm_add_pd(rinv00,_mm_mul_pd(krf,rsq00)),crf));
254             felec            = _mm_mul_pd(qq00,_mm_sub_pd(_mm_mul_pd(rinv00,rinvsq00),krf2));
255
256             /* LENNARD-JONES DISPERSION/REPULSION */
257
258             rinvsix          = _mm_mul_pd(_mm_mul_pd(rinvsq00,rinvsq00),rinvsq00);
259             vvdw6            = _mm_mul_pd(c6_00,rinvsix);
260             vvdw12           = _mm_mul_pd(c12_00,_mm_mul_pd(rinvsix,rinvsix));
261             vvdw             = _mm_sub_pd( _mm_mul_pd(vvdw12,one_twelfth) , _mm_mul_pd(vvdw6,one_sixth) );
262             fvdw             = _mm_mul_pd(_mm_sub_pd(vvdw12,vvdw6),rinvsq00);
263
264             d                = _mm_sub_pd(r00,rswitch);
265             d                = _mm_max_pd(d,_mm_setzero_pd());
266             d2               = _mm_mul_pd(d,d);
267             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_add_pd(swV3,_mm_mul_pd(d,_mm_add_pd(swV4,_mm_mul_pd(d,swV5)))))));
268
269             dsw              = _mm_mul_pd(d2,_mm_add_pd(swF2,_mm_mul_pd(d,_mm_add_pd(swF3,_mm_mul_pd(d,swF4)))));
270
271             /* Evaluate switch function */
272             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
273             fvdw             = _mm_sub_pd( _mm_mul_pd(fvdw,sw) , _mm_mul_pd(rinv00,_mm_mul_pd(vvdw,dsw)) );
274             vvdw             = _mm_mul_pd(vvdw,sw);
275             cutoff_mask      = _mm_cmplt_pd(rsq00,rcutoff2);
276
277             /* Update potential sum for this i atom from the interaction with this j atom. */
278             velec            = _mm_and_pd(velec,cutoff_mask);
279             velecsum         = _mm_add_pd(velecsum,velec);
280             vvdw             = _mm_and_pd(vvdw,cutoff_mask);
281             vvdwsum          = _mm_add_pd(vvdwsum,vvdw);
282
283             fscal            = _mm_add_pd(felec,fvdw);
284
285             fscal            = _mm_and_pd(fscal,cutoff_mask);
286
287             /* Calculate temporary vectorial force */
288             tx               = _mm_mul_pd(fscal,dx00);
289             ty               = _mm_mul_pd(fscal,dy00);
290             tz               = _mm_mul_pd(fscal,dz00);
291
292             /* Update vectorial force */
293             fix0             = _mm_add_pd(fix0,tx);
294             fiy0             = _mm_add_pd(fiy0,ty);
295             fiz0             = _mm_add_pd(fiz0,tz);
296
297             fjx0             = _mm_add_pd(fjx0,tx);
298             fjy0             = _mm_add_pd(fjy0,ty);
299             fjz0             = _mm_add_pd(fjz0,tz);
300
301             }
302
303             /**************************
304              * CALCULATE INTERACTIONS *
305              **************************/
306
307             if (gmx_mm_any_lt(rsq10,rcutoff2))
308             {
309
310             /* Compute parameters for interactions between i and j atoms */
311             qq10             = _mm_mul_pd(iq1,jq0);
312
313             /* REACTION-FIELD ELECTROSTATICS */
314             velec            = _mm_mul_pd(qq10,_mm_sub_pd(_mm_add_pd(rinv10,_mm_mul_pd(krf,rsq10)),crf));
315             felec            = _mm_mul_pd(qq10,_mm_sub_pd(_mm_mul_pd(rinv10,rinvsq10),krf2));
316
317             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
318
319             /* Update potential sum for this i atom from the interaction with this j atom. */
320             velec            = _mm_and_pd(velec,cutoff_mask);
321             velecsum         = _mm_add_pd(velecsum,velec);
322
323             fscal            = felec;
324
325             fscal            = _mm_and_pd(fscal,cutoff_mask);
326
327             /* Calculate temporary vectorial force */
328             tx               = _mm_mul_pd(fscal,dx10);
329             ty               = _mm_mul_pd(fscal,dy10);
330             tz               = _mm_mul_pd(fscal,dz10);
331
332             /* Update vectorial force */
333             fix1             = _mm_add_pd(fix1,tx);
334             fiy1             = _mm_add_pd(fiy1,ty);
335             fiz1             = _mm_add_pd(fiz1,tz);
336
337             fjx0             = _mm_add_pd(fjx0,tx);
338             fjy0             = _mm_add_pd(fjy0,ty);
339             fjz0             = _mm_add_pd(fjz0,tz);
340
341             }
342
343             /**************************
344              * CALCULATE INTERACTIONS *
345              **************************/
346
347             if (gmx_mm_any_lt(rsq20,rcutoff2))
348             {
349
350             /* Compute parameters for interactions between i and j atoms */
351             qq20             = _mm_mul_pd(iq2,jq0);
352
353             /* REACTION-FIELD ELECTROSTATICS */
354             velec            = _mm_mul_pd(qq20,_mm_sub_pd(_mm_add_pd(rinv20,_mm_mul_pd(krf,rsq20)),crf));
355             felec            = _mm_mul_pd(qq20,_mm_sub_pd(_mm_mul_pd(rinv20,rinvsq20),krf2));
356
357             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
358
359             /* Update potential sum for this i atom from the interaction with this j atom. */
360             velec            = _mm_and_pd(velec,cutoff_mask);
361             velecsum         = _mm_add_pd(velecsum,velec);
362
363             fscal            = felec;
364
365             fscal            = _mm_and_pd(fscal,cutoff_mask);
366
367             /* Calculate temporary vectorial force */
368             tx               = _mm_mul_pd(fscal,dx20);
369             ty               = _mm_mul_pd(fscal,dy20);
370             tz               = _mm_mul_pd(fscal,dz20);
371
372             /* Update vectorial force */
373             fix2             = _mm_add_pd(fix2,tx);
374             fiy2             = _mm_add_pd(fiy2,ty);
375             fiz2             = _mm_add_pd(fiz2,tz);
376
377             fjx0             = _mm_add_pd(fjx0,tx);
378             fjy0             = _mm_add_pd(fjy0,ty);
379             fjz0             = _mm_add_pd(fjz0,tz);
380
381             }
382
383             gmx_mm_decrement_1rvec_2ptr_swizzle_pd(f+j_coord_offsetA,f+j_coord_offsetB,fjx0,fjy0,fjz0);
384
385             /* Inner loop uses 145 flops */
386         }
387
388         if(jidx<j_index_end)
389         {
390
391             jnrA             = jjnr[jidx];
392             j_coord_offsetA  = DIM*jnrA;
393
394             /* load j atom coordinates */
395             gmx_mm_load_1rvec_1ptr_swizzle_pd(x+j_coord_offsetA,
396                                               &jx0,&jy0,&jz0);
397
398             /* Calculate displacement vector */
399             dx00             = _mm_sub_pd(ix0,jx0);
400             dy00             = _mm_sub_pd(iy0,jy0);
401             dz00             = _mm_sub_pd(iz0,jz0);
402             dx10             = _mm_sub_pd(ix1,jx0);
403             dy10             = _mm_sub_pd(iy1,jy0);
404             dz10             = _mm_sub_pd(iz1,jz0);
405             dx20             = _mm_sub_pd(ix2,jx0);
406             dy20             = _mm_sub_pd(iy2,jy0);
407             dz20             = _mm_sub_pd(iz2,jz0);
408
409             /* Calculate squared distance and things based on it */
410             rsq00            = gmx_mm_calc_rsq_pd(dx00,dy00,dz00);
411             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
412             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
413
414             rinv00           = gmx_mm_invsqrt_pd(rsq00);
415             rinv10           = gmx_mm_invsqrt_pd(rsq10);
416             rinv20           = gmx_mm_invsqrt_pd(rsq20);
417
418             rinvsq00         = _mm_mul_pd(rinv00,rinv00);
419             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
420             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
421
422             /* Load parameters for j particles */
423             jq0              = _mm_load_sd(charge+jnrA+0);
424             vdwjidx0A        = 2*vdwtype[jnrA+0];
425
426             fjx0             = _mm_setzero_pd();
427             fjy0             = _mm_setzero_pd();
428             fjz0             = _mm_setzero_pd();
429
430             /**************************
431              * CALCULATE INTERACTIONS *
432              **************************/
433
434             if (gmx_mm_any_lt(rsq00,rcutoff2))
435             {
436
437             r00              = _mm_mul_pd(rsq00,rinv00);
438
439             /* Compute parameters for interactions between i and j atoms */
440             qq00             = _mm_mul_pd(iq0,jq0);
441             gmx_mm_load_1pair_swizzle_pd(vdwparam+vdwioffset0+vdwjidx0A,&c6_00,&c12_00);
442
443             /* REACTION-FIELD ELECTROSTATICS */
444             velec            = _mm_mul_pd(qq00,_mm_sub_pd(_mm_add_pd(rinv00,_mm_mul_pd(krf,rsq00)),crf));
445             felec            = _mm_mul_pd(qq00,_mm_sub_pd(_mm_mul_pd(rinv00,rinvsq00),krf2));
446
447             /* LENNARD-JONES DISPERSION/REPULSION */
448
449             rinvsix          = _mm_mul_pd(_mm_mul_pd(rinvsq00,rinvsq00),rinvsq00);
450             vvdw6            = _mm_mul_pd(c6_00,rinvsix);
451             vvdw12           = _mm_mul_pd(c12_00,_mm_mul_pd(rinvsix,rinvsix));
452             vvdw             = _mm_sub_pd( _mm_mul_pd(vvdw12,one_twelfth) , _mm_mul_pd(vvdw6,one_sixth) );
453             fvdw             = _mm_mul_pd(_mm_sub_pd(vvdw12,vvdw6),rinvsq00);
454
455             d                = _mm_sub_pd(r00,rswitch);
456             d                = _mm_max_pd(d,_mm_setzero_pd());
457             d2               = _mm_mul_pd(d,d);
458             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_add_pd(swV3,_mm_mul_pd(d,_mm_add_pd(swV4,_mm_mul_pd(d,swV5)))))));
459
460             dsw              = _mm_mul_pd(d2,_mm_add_pd(swF2,_mm_mul_pd(d,_mm_add_pd(swF3,_mm_mul_pd(d,swF4)))));
461
462             /* Evaluate switch function */
463             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
464             fvdw             = _mm_sub_pd( _mm_mul_pd(fvdw,sw) , _mm_mul_pd(rinv00,_mm_mul_pd(vvdw,dsw)) );
465             vvdw             = _mm_mul_pd(vvdw,sw);
466             cutoff_mask      = _mm_cmplt_pd(rsq00,rcutoff2);
467
468             /* Update potential sum for this i atom from the interaction with this j atom. */
469             velec            = _mm_and_pd(velec,cutoff_mask);
470             velec            = _mm_unpacklo_pd(velec,_mm_setzero_pd());
471             velecsum         = _mm_add_pd(velecsum,velec);
472             vvdw             = _mm_and_pd(vvdw,cutoff_mask);
473             vvdw             = _mm_unpacklo_pd(vvdw,_mm_setzero_pd());
474             vvdwsum          = _mm_add_pd(vvdwsum,vvdw);
475
476             fscal            = _mm_add_pd(felec,fvdw);
477
478             fscal            = _mm_and_pd(fscal,cutoff_mask);
479
480             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
481
482             /* Calculate temporary vectorial force */
483             tx               = _mm_mul_pd(fscal,dx00);
484             ty               = _mm_mul_pd(fscal,dy00);
485             tz               = _mm_mul_pd(fscal,dz00);
486
487             /* Update vectorial force */
488             fix0             = _mm_add_pd(fix0,tx);
489             fiy0             = _mm_add_pd(fiy0,ty);
490             fiz0             = _mm_add_pd(fiz0,tz);
491
492             fjx0             = _mm_add_pd(fjx0,tx);
493             fjy0             = _mm_add_pd(fjy0,ty);
494             fjz0             = _mm_add_pd(fjz0,tz);
495
496             }
497
498             /**************************
499              * CALCULATE INTERACTIONS *
500              **************************/
501
502             if (gmx_mm_any_lt(rsq10,rcutoff2))
503             {
504
505             /* Compute parameters for interactions between i and j atoms */
506             qq10             = _mm_mul_pd(iq1,jq0);
507
508             /* REACTION-FIELD ELECTROSTATICS */
509             velec            = _mm_mul_pd(qq10,_mm_sub_pd(_mm_add_pd(rinv10,_mm_mul_pd(krf,rsq10)),crf));
510             felec            = _mm_mul_pd(qq10,_mm_sub_pd(_mm_mul_pd(rinv10,rinvsq10),krf2));
511
512             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
513
514             /* Update potential sum for this i atom from the interaction with this j atom. */
515             velec            = _mm_and_pd(velec,cutoff_mask);
516             velec            = _mm_unpacklo_pd(velec,_mm_setzero_pd());
517             velecsum         = _mm_add_pd(velecsum,velec);
518
519             fscal            = felec;
520
521             fscal            = _mm_and_pd(fscal,cutoff_mask);
522
523             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
524
525             /* Calculate temporary vectorial force */
526             tx               = _mm_mul_pd(fscal,dx10);
527             ty               = _mm_mul_pd(fscal,dy10);
528             tz               = _mm_mul_pd(fscal,dz10);
529
530             /* Update vectorial force */
531             fix1             = _mm_add_pd(fix1,tx);
532             fiy1             = _mm_add_pd(fiy1,ty);
533             fiz1             = _mm_add_pd(fiz1,tz);
534
535             fjx0             = _mm_add_pd(fjx0,tx);
536             fjy0             = _mm_add_pd(fjy0,ty);
537             fjz0             = _mm_add_pd(fjz0,tz);
538
539             }
540
541             /**************************
542              * CALCULATE INTERACTIONS *
543              **************************/
544
545             if (gmx_mm_any_lt(rsq20,rcutoff2))
546             {
547
548             /* Compute parameters for interactions between i and j atoms */
549             qq20             = _mm_mul_pd(iq2,jq0);
550
551             /* REACTION-FIELD ELECTROSTATICS */
552             velec            = _mm_mul_pd(qq20,_mm_sub_pd(_mm_add_pd(rinv20,_mm_mul_pd(krf,rsq20)),crf));
553             felec            = _mm_mul_pd(qq20,_mm_sub_pd(_mm_mul_pd(rinv20,rinvsq20),krf2));
554
555             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
556
557             /* Update potential sum for this i atom from the interaction with this j atom. */
558             velec            = _mm_and_pd(velec,cutoff_mask);
559             velec            = _mm_unpacklo_pd(velec,_mm_setzero_pd());
560             velecsum         = _mm_add_pd(velecsum,velec);
561
562             fscal            = felec;
563
564             fscal            = _mm_and_pd(fscal,cutoff_mask);
565
566             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
567
568             /* Calculate temporary vectorial force */
569             tx               = _mm_mul_pd(fscal,dx20);
570             ty               = _mm_mul_pd(fscal,dy20);
571             tz               = _mm_mul_pd(fscal,dz20);
572
573             /* Update vectorial force */
574             fix2             = _mm_add_pd(fix2,tx);
575             fiy2             = _mm_add_pd(fiy2,ty);
576             fiz2             = _mm_add_pd(fiz2,tz);
577
578             fjx0             = _mm_add_pd(fjx0,tx);
579             fjy0             = _mm_add_pd(fjy0,ty);
580             fjz0             = _mm_add_pd(fjz0,tz);
581
582             }
583
584             gmx_mm_decrement_1rvec_1ptr_swizzle_pd(f+j_coord_offsetA,fjx0,fjy0,fjz0);
585
586             /* Inner loop uses 145 flops */
587         }
588
589         /* End of innermost loop */
590
591         gmx_mm_update_iforce_3atom_swizzle_pd(fix0,fiy0,fiz0,fix1,fiy1,fiz1,fix2,fiy2,fiz2,
592                                               f+i_coord_offset,fshift+i_shift_offset);
593
594         ggid                        = gid[iidx];
595         /* Update potential energies */
596         gmx_mm_update_1pot_pd(velecsum,kernel_data->energygrp_elec+ggid);
597         gmx_mm_update_1pot_pd(vvdwsum,kernel_data->energygrp_vdw+ggid);
598
599         /* Increment number of inner iterations */
600         inneriter                  += j_index_end - j_index_start;
601
602         /* Outer loop uses 20 flops */
603     }
604
605     /* Increment number of outer iterations */
606     outeriter        += nri;
607
608     /* Update outer/inner flops */
609
610     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_VDW_W3_VF,outeriter*20 + inneriter*145);
611 }
612 /*
613  * Gromacs nonbonded kernel:   nb_kernel_ElecRFCut_VdwLJSw_GeomW3P1_F_sse2_double
614  * Electrostatics interaction: ReactionField
615  * VdW interaction:            LennardJones
616  * Geometry:                   Water3-Particle
617  * Calculate force/pot:        Force
618  */
619 void
620 nb_kernel_ElecRFCut_VdwLJSw_GeomW3P1_F_sse2_double
621                     (t_nblist                    * gmx_restrict       nlist,
622                      rvec                        * gmx_restrict          xx,
623                      rvec                        * gmx_restrict          ff,
624                      t_forcerec                  * gmx_restrict          fr,
625                      t_mdatoms                   * gmx_restrict     mdatoms,
626                      nb_kernel_data_t gmx_unused * gmx_restrict kernel_data,
627                      t_nrnb                      * gmx_restrict        nrnb)
628 {
629     /* Suffixes 0,1,2,3 refer to particle indices for waters in the inner or outer loop, or
630      * just 0 for non-waters.
631      * Suffixes A,B refer to j loop unrolling done with SSE double precision, e.g. for the two different
632      * jnr indices corresponding to data put in the four positions in the SIMD register.
633      */
634     int              i_shift_offset,i_coord_offset,outeriter,inneriter;
635     int              j_index_start,j_index_end,jidx,nri,inr,ggid,iidx;
636     int              jnrA,jnrB;
637     int              j_coord_offsetA,j_coord_offsetB;
638     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
639     real             rcutoff_scalar;
640     real             *shiftvec,*fshift,*x,*f;
641     __m128d          tx,ty,tz,fscal,rcutoff,rcutoff2,jidxall;
642     int              vdwioffset0;
643     __m128d          ix0,iy0,iz0,fix0,fiy0,fiz0,iq0,isai0;
644     int              vdwioffset1;
645     __m128d          ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
646     int              vdwioffset2;
647     __m128d          ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
648     int              vdwjidx0A,vdwjidx0B;
649     __m128d          jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
650     __m128d          dx00,dy00,dz00,rsq00,rinv00,rinvsq00,r00,qq00,c6_00,c12_00;
651     __m128d          dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10;
652     __m128d          dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20;
653     __m128d          velec,felec,velecsum,facel,crf,krf,krf2;
654     real             *charge;
655     int              nvdwtype;
656     __m128d          rinvsix,rvdw,vvdw,vvdw6,vvdw12,fvdw,fvdw6,fvdw12,vvdwsum,sh_vdw_invrcut6;
657     int              *vdwtype;
658     real             *vdwparam;
659     __m128d          one_sixth   = _mm_set1_pd(1.0/6.0);
660     __m128d          one_twelfth = _mm_set1_pd(1.0/12.0);
661     __m128d          rswitch,swV3,swV4,swV5,swF2,swF3,swF4,d,d2,sw,dsw;
662     real             rswitch_scalar,d_scalar;
663     __m128d          dummy_mask,cutoff_mask;
664     __m128d          signbit   = gmx_mm_castsi128_pd( _mm_set_epi32(0x80000000,0x00000000,0x80000000,0x00000000) );
665     __m128d          one     = _mm_set1_pd(1.0);
666     __m128d          two     = _mm_set1_pd(2.0);
667     x                = xx[0];
668     f                = ff[0];
669
670     nri              = nlist->nri;
671     iinr             = nlist->iinr;
672     jindex           = nlist->jindex;
673     jjnr             = nlist->jjnr;
674     shiftidx         = nlist->shift;
675     gid              = nlist->gid;
676     shiftvec         = fr->shift_vec[0];
677     fshift           = fr->fshift[0];
678     facel            = _mm_set1_pd(fr->epsfac);
679     charge           = mdatoms->chargeA;
680     krf              = _mm_set1_pd(fr->ic->k_rf);
681     krf2             = _mm_set1_pd(fr->ic->k_rf*2.0);
682     crf              = _mm_set1_pd(fr->ic->c_rf);
683     nvdwtype         = fr->ntype;
684     vdwparam         = fr->nbfp;
685     vdwtype          = mdatoms->typeA;
686
687     /* Setup water-specific parameters */
688     inr              = nlist->iinr[0];
689     iq0              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+0]));
690     iq1              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+1]));
691     iq2              = _mm_mul_pd(facel,_mm_set1_pd(charge[inr+2]));
692     vdwioffset0      = 2*nvdwtype*vdwtype[inr+0];
693
694     /* When we use explicit cutoffs the value must be identical for elec and VdW, so use elec as an arbitrary choice */
695     rcutoff_scalar   = fr->rcoulomb;
696     rcutoff          = _mm_set1_pd(rcutoff_scalar);
697     rcutoff2         = _mm_mul_pd(rcutoff,rcutoff);
698
699     rswitch_scalar   = fr->rvdw_switch;
700     rswitch          = _mm_set1_pd(rswitch_scalar);
701     /* Setup switch parameters */
702     d_scalar         = rcutoff_scalar-rswitch_scalar;
703     d                = _mm_set1_pd(d_scalar);
704     swV3             = _mm_set1_pd(-10.0/(d_scalar*d_scalar*d_scalar));
705     swV4             = _mm_set1_pd( 15.0/(d_scalar*d_scalar*d_scalar*d_scalar));
706     swV5             = _mm_set1_pd( -6.0/(d_scalar*d_scalar*d_scalar*d_scalar*d_scalar));
707     swF2             = _mm_set1_pd(-30.0/(d_scalar*d_scalar*d_scalar));
708     swF3             = _mm_set1_pd( 60.0/(d_scalar*d_scalar*d_scalar*d_scalar));
709     swF4             = _mm_set1_pd(-30.0/(d_scalar*d_scalar*d_scalar*d_scalar*d_scalar));
710
711     /* Avoid stupid compiler warnings */
712     jnrA = jnrB = 0;
713     j_coord_offsetA = 0;
714     j_coord_offsetB = 0;
715
716     outeriter        = 0;
717     inneriter        = 0;
718
719     /* Start outer loop over neighborlists */
720     for(iidx=0; iidx<nri; iidx++)
721     {
722         /* Load shift vector for this list */
723         i_shift_offset   = DIM*shiftidx[iidx];
724
725         /* Load limits for loop over neighbors */
726         j_index_start    = jindex[iidx];
727         j_index_end      = jindex[iidx+1];
728
729         /* Get outer coordinate index */
730         inr              = iinr[iidx];
731         i_coord_offset   = DIM*inr;
732
733         /* Load i particle coords and add shift vector */
734         gmx_mm_load_shift_and_3rvec_broadcast_pd(shiftvec+i_shift_offset,x+i_coord_offset,
735                                                  &ix0,&iy0,&iz0,&ix1,&iy1,&iz1,&ix2,&iy2,&iz2);
736
737         fix0             = _mm_setzero_pd();
738         fiy0             = _mm_setzero_pd();
739         fiz0             = _mm_setzero_pd();
740         fix1             = _mm_setzero_pd();
741         fiy1             = _mm_setzero_pd();
742         fiz1             = _mm_setzero_pd();
743         fix2             = _mm_setzero_pd();
744         fiy2             = _mm_setzero_pd();
745         fiz2             = _mm_setzero_pd();
746
747         /* Start inner kernel loop */
748         for(jidx=j_index_start; jidx<j_index_end-1; jidx+=2)
749         {
750
751             /* Get j neighbor index, and coordinate index */
752             jnrA             = jjnr[jidx];
753             jnrB             = jjnr[jidx+1];
754             j_coord_offsetA  = DIM*jnrA;
755             j_coord_offsetB  = DIM*jnrB;
756
757             /* load j atom coordinates */
758             gmx_mm_load_1rvec_2ptr_swizzle_pd(x+j_coord_offsetA,x+j_coord_offsetB,
759                                               &jx0,&jy0,&jz0);
760
761             /* Calculate displacement vector */
762             dx00             = _mm_sub_pd(ix0,jx0);
763             dy00             = _mm_sub_pd(iy0,jy0);
764             dz00             = _mm_sub_pd(iz0,jz0);
765             dx10             = _mm_sub_pd(ix1,jx0);
766             dy10             = _mm_sub_pd(iy1,jy0);
767             dz10             = _mm_sub_pd(iz1,jz0);
768             dx20             = _mm_sub_pd(ix2,jx0);
769             dy20             = _mm_sub_pd(iy2,jy0);
770             dz20             = _mm_sub_pd(iz2,jz0);
771
772             /* Calculate squared distance and things based on it */
773             rsq00            = gmx_mm_calc_rsq_pd(dx00,dy00,dz00);
774             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
775             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
776
777             rinv00           = gmx_mm_invsqrt_pd(rsq00);
778             rinv10           = gmx_mm_invsqrt_pd(rsq10);
779             rinv20           = gmx_mm_invsqrt_pd(rsq20);
780
781             rinvsq00         = _mm_mul_pd(rinv00,rinv00);
782             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
783             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
784
785             /* Load parameters for j particles */
786             jq0              = gmx_mm_load_2real_swizzle_pd(charge+jnrA+0,charge+jnrB+0);
787             vdwjidx0A        = 2*vdwtype[jnrA+0];
788             vdwjidx0B        = 2*vdwtype[jnrB+0];
789
790             fjx0             = _mm_setzero_pd();
791             fjy0             = _mm_setzero_pd();
792             fjz0             = _mm_setzero_pd();
793
794             /**************************
795              * CALCULATE INTERACTIONS *
796              **************************/
797
798             if (gmx_mm_any_lt(rsq00,rcutoff2))
799             {
800
801             r00              = _mm_mul_pd(rsq00,rinv00);
802
803             /* Compute parameters for interactions between i and j atoms */
804             qq00             = _mm_mul_pd(iq0,jq0);
805             gmx_mm_load_2pair_swizzle_pd(vdwparam+vdwioffset0+vdwjidx0A,
806                                          vdwparam+vdwioffset0+vdwjidx0B,&c6_00,&c12_00);
807
808             /* REACTION-FIELD ELECTROSTATICS */
809             felec            = _mm_mul_pd(qq00,_mm_sub_pd(_mm_mul_pd(rinv00,rinvsq00),krf2));
810
811             /* LENNARD-JONES DISPERSION/REPULSION */
812
813             rinvsix          = _mm_mul_pd(_mm_mul_pd(rinvsq00,rinvsq00),rinvsq00);
814             vvdw6            = _mm_mul_pd(c6_00,rinvsix);
815             vvdw12           = _mm_mul_pd(c12_00,_mm_mul_pd(rinvsix,rinvsix));
816             vvdw             = _mm_sub_pd( _mm_mul_pd(vvdw12,one_twelfth) , _mm_mul_pd(vvdw6,one_sixth) );
817             fvdw             = _mm_mul_pd(_mm_sub_pd(vvdw12,vvdw6),rinvsq00);
818
819             d                = _mm_sub_pd(r00,rswitch);
820             d                = _mm_max_pd(d,_mm_setzero_pd());
821             d2               = _mm_mul_pd(d,d);
822             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_add_pd(swV3,_mm_mul_pd(d,_mm_add_pd(swV4,_mm_mul_pd(d,swV5)))))));
823
824             dsw              = _mm_mul_pd(d2,_mm_add_pd(swF2,_mm_mul_pd(d,_mm_add_pd(swF3,_mm_mul_pd(d,swF4)))));
825
826             /* Evaluate switch function */
827             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
828             fvdw             = _mm_sub_pd( _mm_mul_pd(fvdw,sw) , _mm_mul_pd(rinv00,_mm_mul_pd(vvdw,dsw)) );
829             cutoff_mask      = _mm_cmplt_pd(rsq00,rcutoff2);
830
831             fscal            = _mm_add_pd(felec,fvdw);
832
833             fscal            = _mm_and_pd(fscal,cutoff_mask);
834
835             /* Calculate temporary vectorial force */
836             tx               = _mm_mul_pd(fscal,dx00);
837             ty               = _mm_mul_pd(fscal,dy00);
838             tz               = _mm_mul_pd(fscal,dz00);
839
840             /* Update vectorial force */
841             fix0             = _mm_add_pd(fix0,tx);
842             fiy0             = _mm_add_pd(fiy0,ty);
843             fiz0             = _mm_add_pd(fiz0,tz);
844
845             fjx0             = _mm_add_pd(fjx0,tx);
846             fjy0             = _mm_add_pd(fjy0,ty);
847             fjz0             = _mm_add_pd(fjz0,tz);
848
849             }
850
851             /**************************
852              * CALCULATE INTERACTIONS *
853              **************************/
854
855             if (gmx_mm_any_lt(rsq10,rcutoff2))
856             {
857
858             /* Compute parameters for interactions between i and j atoms */
859             qq10             = _mm_mul_pd(iq1,jq0);
860
861             /* REACTION-FIELD ELECTROSTATICS */
862             felec            = _mm_mul_pd(qq10,_mm_sub_pd(_mm_mul_pd(rinv10,rinvsq10),krf2));
863
864             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
865
866             fscal            = felec;
867
868             fscal            = _mm_and_pd(fscal,cutoff_mask);
869
870             /* Calculate temporary vectorial force */
871             tx               = _mm_mul_pd(fscal,dx10);
872             ty               = _mm_mul_pd(fscal,dy10);
873             tz               = _mm_mul_pd(fscal,dz10);
874
875             /* Update vectorial force */
876             fix1             = _mm_add_pd(fix1,tx);
877             fiy1             = _mm_add_pd(fiy1,ty);
878             fiz1             = _mm_add_pd(fiz1,tz);
879
880             fjx0             = _mm_add_pd(fjx0,tx);
881             fjy0             = _mm_add_pd(fjy0,ty);
882             fjz0             = _mm_add_pd(fjz0,tz);
883
884             }
885
886             /**************************
887              * CALCULATE INTERACTIONS *
888              **************************/
889
890             if (gmx_mm_any_lt(rsq20,rcutoff2))
891             {
892
893             /* Compute parameters for interactions between i and j atoms */
894             qq20             = _mm_mul_pd(iq2,jq0);
895
896             /* REACTION-FIELD ELECTROSTATICS */
897             felec            = _mm_mul_pd(qq20,_mm_sub_pd(_mm_mul_pd(rinv20,rinvsq20),krf2));
898
899             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
900
901             fscal            = felec;
902
903             fscal            = _mm_and_pd(fscal,cutoff_mask);
904
905             /* Calculate temporary vectorial force */
906             tx               = _mm_mul_pd(fscal,dx20);
907             ty               = _mm_mul_pd(fscal,dy20);
908             tz               = _mm_mul_pd(fscal,dz20);
909
910             /* Update vectorial force */
911             fix2             = _mm_add_pd(fix2,tx);
912             fiy2             = _mm_add_pd(fiy2,ty);
913             fiz2             = _mm_add_pd(fiz2,tz);
914
915             fjx0             = _mm_add_pd(fjx0,tx);
916             fjy0             = _mm_add_pd(fjy0,ty);
917             fjz0             = _mm_add_pd(fjz0,tz);
918
919             }
920
921             gmx_mm_decrement_1rvec_2ptr_swizzle_pd(f+j_coord_offsetA,f+j_coord_offsetB,fjx0,fjy0,fjz0);
922
923             /* Inner loop uses 124 flops */
924         }
925
926         if(jidx<j_index_end)
927         {
928
929             jnrA             = jjnr[jidx];
930             j_coord_offsetA  = DIM*jnrA;
931
932             /* load j atom coordinates */
933             gmx_mm_load_1rvec_1ptr_swizzle_pd(x+j_coord_offsetA,
934                                               &jx0,&jy0,&jz0);
935
936             /* Calculate displacement vector */
937             dx00             = _mm_sub_pd(ix0,jx0);
938             dy00             = _mm_sub_pd(iy0,jy0);
939             dz00             = _mm_sub_pd(iz0,jz0);
940             dx10             = _mm_sub_pd(ix1,jx0);
941             dy10             = _mm_sub_pd(iy1,jy0);
942             dz10             = _mm_sub_pd(iz1,jz0);
943             dx20             = _mm_sub_pd(ix2,jx0);
944             dy20             = _mm_sub_pd(iy2,jy0);
945             dz20             = _mm_sub_pd(iz2,jz0);
946
947             /* Calculate squared distance and things based on it */
948             rsq00            = gmx_mm_calc_rsq_pd(dx00,dy00,dz00);
949             rsq10            = gmx_mm_calc_rsq_pd(dx10,dy10,dz10);
950             rsq20            = gmx_mm_calc_rsq_pd(dx20,dy20,dz20);
951
952             rinv00           = gmx_mm_invsqrt_pd(rsq00);
953             rinv10           = gmx_mm_invsqrt_pd(rsq10);
954             rinv20           = gmx_mm_invsqrt_pd(rsq20);
955
956             rinvsq00         = _mm_mul_pd(rinv00,rinv00);
957             rinvsq10         = _mm_mul_pd(rinv10,rinv10);
958             rinvsq20         = _mm_mul_pd(rinv20,rinv20);
959
960             /* Load parameters for j particles */
961             jq0              = _mm_load_sd(charge+jnrA+0);
962             vdwjidx0A        = 2*vdwtype[jnrA+0];
963
964             fjx0             = _mm_setzero_pd();
965             fjy0             = _mm_setzero_pd();
966             fjz0             = _mm_setzero_pd();
967
968             /**************************
969              * CALCULATE INTERACTIONS *
970              **************************/
971
972             if (gmx_mm_any_lt(rsq00,rcutoff2))
973             {
974
975             r00              = _mm_mul_pd(rsq00,rinv00);
976
977             /* Compute parameters for interactions between i and j atoms */
978             qq00             = _mm_mul_pd(iq0,jq0);
979             gmx_mm_load_1pair_swizzle_pd(vdwparam+vdwioffset0+vdwjidx0A,&c6_00,&c12_00);
980
981             /* REACTION-FIELD ELECTROSTATICS */
982             felec            = _mm_mul_pd(qq00,_mm_sub_pd(_mm_mul_pd(rinv00,rinvsq00),krf2));
983
984             /* LENNARD-JONES DISPERSION/REPULSION */
985
986             rinvsix          = _mm_mul_pd(_mm_mul_pd(rinvsq00,rinvsq00),rinvsq00);
987             vvdw6            = _mm_mul_pd(c6_00,rinvsix);
988             vvdw12           = _mm_mul_pd(c12_00,_mm_mul_pd(rinvsix,rinvsix));
989             vvdw             = _mm_sub_pd( _mm_mul_pd(vvdw12,one_twelfth) , _mm_mul_pd(vvdw6,one_sixth) );
990             fvdw             = _mm_mul_pd(_mm_sub_pd(vvdw12,vvdw6),rinvsq00);
991
992             d                = _mm_sub_pd(r00,rswitch);
993             d                = _mm_max_pd(d,_mm_setzero_pd());
994             d2               = _mm_mul_pd(d,d);
995             sw               = _mm_add_pd(one,_mm_mul_pd(d2,_mm_mul_pd(d,_mm_add_pd(swV3,_mm_mul_pd(d,_mm_add_pd(swV4,_mm_mul_pd(d,swV5)))))));
996
997             dsw              = _mm_mul_pd(d2,_mm_add_pd(swF2,_mm_mul_pd(d,_mm_add_pd(swF3,_mm_mul_pd(d,swF4)))));
998
999             /* Evaluate switch function */
1000             /* fscal'=f'/r=-(v*sw)'/r=-(v'*sw+v*dsw)/r=-v'*sw/r-v*dsw/r=fscal*sw-v*dsw/r */
1001             fvdw             = _mm_sub_pd( _mm_mul_pd(fvdw,sw) , _mm_mul_pd(rinv00,_mm_mul_pd(vvdw,dsw)) );
1002             cutoff_mask      = _mm_cmplt_pd(rsq00,rcutoff2);
1003
1004             fscal            = _mm_add_pd(felec,fvdw);
1005
1006             fscal            = _mm_and_pd(fscal,cutoff_mask);
1007
1008             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
1009
1010             /* Calculate temporary vectorial force */
1011             tx               = _mm_mul_pd(fscal,dx00);
1012             ty               = _mm_mul_pd(fscal,dy00);
1013             tz               = _mm_mul_pd(fscal,dz00);
1014
1015             /* Update vectorial force */
1016             fix0             = _mm_add_pd(fix0,tx);
1017             fiy0             = _mm_add_pd(fiy0,ty);
1018             fiz0             = _mm_add_pd(fiz0,tz);
1019
1020             fjx0             = _mm_add_pd(fjx0,tx);
1021             fjy0             = _mm_add_pd(fjy0,ty);
1022             fjz0             = _mm_add_pd(fjz0,tz);
1023
1024             }
1025
1026             /**************************
1027              * CALCULATE INTERACTIONS *
1028              **************************/
1029
1030             if (gmx_mm_any_lt(rsq10,rcutoff2))
1031             {
1032
1033             /* Compute parameters for interactions between i and j atoms */
1034             qq10             = _mm_mul_pd(iq1,jq0);
1035
1036             /* REACTION-FIELD ELECTROSTATICS */
1037             felec            = _mm_mul_pd(qq10,_mm_sub_pd(_mm_mul_pd(rinv10,rinvsq10),krf2));
1038
1039             cutoff_mask      = _mm_cmplt_pd(rsq10,rcutoff2);
1040
1041             fscal            = felec;
1042
1043             fscal            = _mm_and_pd(fscal,cutoff_mask);
1044
1045             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
1046
1047             /* Calculate temporary vectorial force */
1048             tx               = _mm_mul_pd(fscal,dx10);
1049             ty               = _mm_mul_pd(fscal,dy10);
1050             tz               = _mm_mul_pd(fscal,dz10);
1051
1052             /* Update vectorial force */
1053             fix1             = _mm_add_pd(fix1,tx);
1054             fiy1             = _mm_add_pd(fiy1,ty);
1055             fiz1             = _mm_add_pd(fiz1,tz);
1056
1057             fjx0             = _mm_add_pd(fjx0,tx);
1058             fjy0             = _mm_add_pd(fjy0,ty);
1059             fjz0             = _mm_add_pd(fjz0,tz);
1060
1061             }
1062
1063             /**************************
1064              * CALCULATE INTERACTIONS *
1065              **************************/
1066
1067             if (gmx_mm_any_lt(rsq20,rcutoff2))
1068             {
1069
1070             /* Compute parameters for interactions between i and j atoms */
1071             qq20             = _mm_mul_pd(iq2,jq0);
1072
1073             /* REACTION-FIELD ELECTROSTATICS */
1074             felec            = _mm_mul_pd(qq20,_mm_sub_pd(_mm_mul_pd(rinv20,rinvsq20),krf2));
1075
1076             cutoff_mask      = _mm_cmplt_pd(rsq20,rcutoff2);
1077
1078             fscal            = felec;
1079
1080             fscal            = _mm_and_pd(fscal,cutoff_mask);
1081
1082             fscal            = _mm_unpacklo_pd(fscal,_mm_setzero_pd());
1083
1084             /* Calculate temporary vectorial force */
1085             tx               = _mm_mul_pd(fscal,dx20);
1086             ty               = _mm_mul_pd(fscal,dy20);
1087             tz               = _mm_mul_pd(fscal,dz20);
1088
1089             /* Update vectorial force */
1090             fix2             = _mm_add_pd(fix2,tx);
1091             fiy2             = _mm_add_pd(fiy2,ty);
1092             fiz2             = _mm_add_pd(fiz2,tz);
1093
1094             fjx0             = _mm_add_pd(fjx0,tx);
1095             fjy0             = _mm_add_pd(fjy0,ty);
1096             fjz0             = _mm_add_pd(fjz0,tz);
1097
1098             }
1099
1100             gmx_mm_decrement_1rvec_1ptr_swizzle_pd(f+j_coord_offsetA,fjx0,fjy0,fjz0);
1101
1102             /* Inner loop uses 124 flops */
1103         }
1104
1105         /* End of innermost loop */
1106
1107         gmx_mm_update_iforce_3atom_swizzle_pd(fix0,fiy0,fiz0,fix1,fiy1,fiz1,fix2,fiy2,fiz2,
1108                                               f+i_coord_offset,fshift+i_shift_offset);
1109
1110         /* Increment number of inner iterations */
1111         inneriter                  += j_index_end - j_index_start;
1112
1113         /* Outer loop uses 18 flops */
1114     }
1115
1116     /* Increment number of outer iterations */
1117     outeriter        += nri;
1118
1119     /* Update outer/inner flops */
1120
1121     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_VDW_W3_F,outeriter*18 + inneriter*124);
1122 }