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