5e1268fb5f68aa3c2095623bf9270264c26eb441
[alexxy/gromacs.git] / src / gromacs / gmxlib / nonbonded / nb_kernel_c / nb_kernel_ElecEwSh_VdwLJEwSh_GeomW4P1_c.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 c kernel generator.
37  */
38 #include "config.h"
39
40 #include <math.h>
41
42 #include "../nb_kernel.h"
43 #include "types/simple.h"
44 #include "gromacs/math/vec.h"
45 #include "nrnb.h"
46
47 /*
48  * Gromacs nonbonded kernel:   nb_kernel_ElecEwSh_VdwLJEwSh_GeomW4P1_VF_c
49  * Electrostatics interaction: Ewald
50  * VdW interaction:            LJEwald
51  * Geometry:                   Water4-Particle
52  * Calculate force/pot:        PotentialAndForce
53  */
54 void
55 nb_kernel_ElecEwSh_VdwLJEwSh_GeomW4P1_VF_c
56                     (t_nblist                    * gmx_restrict       nlist,
57                      rvec                        * gmx_restrict          xx,
58                      rvec                        * gmx_restrict          ff,
59                      t_forcerec                  * gmx_restrict          fr,
60                      t_mdatoms                   * gmx_restrict     mdatoms,
61                      nb_kernel_data_t gmx_unused * gmx_restrict kernel_data,
62                      t_nrnb                      * gmx_restrict        nrnb)
63 {
64     int              i_shift_offset,i_coord_offset,j_coord_offset;
65     int              j_index_start,j_index_end;
66     int              nri,inr,ggid,iidx,jidx,jnr,outeriter,inneriter;
67     real             shX,shY,shZ,tx,ty,tz,fscal,rcutoff,rcutoff2;
68     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
69     real             *shiftvec,*fshift,*x,*f;
70     int              vdwioffset0;
71     real             ix0,iy0,iz0,fix0,fiy0,fiz0,iq0,isai0;
72     int              vdwioffset1;
73     real             ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
74     int              vdwioffset2;
75     real             ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
76     int              vdwioffset3;
77     real             ix3,iy3,iz3,fix3,fiy3,fiz3,iq3,isai3;
78     int              vdwjidx0;
79     real             jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
80     real             dx00,dy00,dz00,rsq00,rinv00,rinvsq00,r00,qq00,c6_00,c12_00,cexp1_00,cexp2_00;
81     real             dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10,cexp1_10,cexp2_10;
82     real             dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20,cexp1_20,cexp2_20;
83     real             dx30,dy30,dz30,rsq30,rinv30,rinvsq30,r30,qq30,c6_30,c12_30,cexp1_30,cexp2_30;
84     real             velec,felec,velecsum,facel,crf,krf,krf2;
85     real             *charge;
86     int              nvdwtype;
87     real             rinvsix,rvdw,vvdw,vvdw6,vvdw12,fvdw,fvdw6,fvdw12,vvdwsum,br,vvdwexp,sh_vdw_invrcut6;
88     int              *vdwtype;
89     real             *vdwparam;
90     real             c6grid_00;
91     real             c6grid_10;
92     real             c6grid_20;
93     real             c6grid_30;
94     real             ewclj,ewclj2,ewclj6,ewcljrsq,poly,exponent,sh_lj_ewald;
95     real             *vdwgridparam;
96     int              ewitab;
97     real             ewtabscale,eweps,sh_ewald,ewrt,ewtabhalfspace;
98     real             *ewtab;
99
100     x                = xx[0];
101     f                = ff[0];
102
103     nri              = nlist->nri;
104     iinr             = nlist->iinr;
105     jindex           = nlist->jindex;
106     jjnr             = nlist->jjnr;
107     shiftidx         = nlist->shift;
108     gid              = nlist->gid;
109     shiftvec         = fr->shift_vec[0];
110     fshift           = fr->fshift[0];
111     facel            = fr->epsfac;
112     charge           = mdatoms->chargeA;
113     nvdwtype         = fr->ntype;
114     vdwparam         = fr->nbfp;
115     vdwtype          = mdatoms->typeA;
116     vdwgridparam     = fr->ljpme_c6grid;
117     ewclj            = fr->ewaldcoeff_lj;
118     sh_lj_ewald      = fr->ic->sh_lj_ewald;
119     ewclj2           = ewclj*ewclj;
120     ewclj6           = ewclj2*ewclj2*ewclj2;
121
122     sh_ewald         = fr->ic->sh_ewald;
123     ewtab            = fr->ic->tabq_coul_FDV0;
124     ewtabscale       = fr->ic->tabq_scale;
125     ewtabhalfspace   = 0.5/ewtabscale;
126
127     /* Setup water-specific parameters */
128     inr              = nlist->iinr[0];
129     iq1              = facel*charge[inr+1];
130     iq2              = facel*charge[inr+2];
131     iq3              = facel*charge[inr+3];
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          = fr->rcoulomb;
136     rcutoff2         = rcutoff*rcutoff;
137
138     sh_vdw_invrcut6  = fr->ic->sh_invrc6;
139     rvdw             = fr->rvdw;
140
141     outeriter        = 0;
142     inneriter        = 0;
143
144     /* Start outer loop over neighborlists */
145     for(iidx=0; iidx<nri; iidx++)
146     {
147         /* Load shift vector for this list */
148         i_shift_offset   = DIM*shiftidx[iidx];
149         shX              = shiftvec[i_shift_offset+XX];
150         shY              = shiftvec[i_shift_offset+YY];
151         shZ              = shiftvec[i_shift_offset+ZZ];
152
153         /* Load limits for loop over neighbors */
154         j_index_start    = jindex[iidx];
155         j_index_end      = jindex[iidx+1];
156
157         /* Get outer coordinate index */
158         inr              = iinr[iidx];
159         i_coord_offset   = DIM*inr;
160
161         /* Load i particle coords and add shift vector */
162         ix0              = shX + x[i_coord_offset+DIM*0+XX];
163         iy0              = shY + x[i_coord_offset+DIM*0+YY];
164         iz0              = shZ + x[i_coord_offset+DIM*0+ZZ];
165         ix1              = shX + x[i_coord_offset+DIM*1+XX];
166         iy1              = shY + x[i_coord_offset+DIM*1+YY];
167         iz1              = shZ + x[i_coord_offset+DIM*1+ZZ];
168         ix2              = shX + x[i_coord_offset+DIM*2+XX];
169         iy2              = shY + x[i_coord_offset+DIM*2+YY];
170         iz2              = shZ + x[i_coord_offset+DIM*2+ZZ];
171         ix3              = shX + x[i_coord_offset+DIM*3+XX];
172         iy3              = shY + x[i_coord_offset+DIM*3+YY];
173         iz3              = shZ + x[i_coord_offset+DIM*3+ZZ];
174
175         fix0             = 0.0;
176         fiy0             = 0.0;
177         fiz0             = 0.0;
178         fix1             = 0.0;
179         fiy1             = 0.0;
180         fiz1             = 0.0;
181         fix2             = 0.0;
182         fiy2             = 0.0;
183         fiz2             = 0.0;
184         fix3             = 0.0;
185         fiy3             = 0.0;
186         fiz3             = 0.0;
187
188         /* Reset potential sums */
189         velecsum         = 0.0;
190         vvdwsum          = 0.0;
191
192         /* Start inner kernel loop */
193         for(jidx=j_index_start; jidx<j_index_end; jidx++)
194         {
195             /* Get j neighbor index, and coordinate index */
196             jnr              = jjnr[jidx];
197             j_coord_offset   = DIM*jnr;
198
199             /* load j atom coordinates */
200             jx0              = x[j_coord_offset+DIM*0+XX];
201             jy0              = x[j_coord_offset+DIM*0+YY];
202             jz0              = x[j_coord_offset+DIM*0+ZZ];
203
204             /* Calculate displacement vector */
205             dx00             = ix0 - jx0;
206             dy00             = iy0 - jy0;
207             dz00             = iz0 - jz0;
208             dx10             = ix1 - jx0;
209             dy10             = iy1 - jy0;
210             dz10             = iz1 - jz0;
211             dx20             = ix2 - jx0;
212             dy20             = iy2 - jy0;
213             dz20             = iz2 - jz0;
214             dx30             = ix3 - jx0;
215             dy30             = iy3 - jy0;
216             dz30             = iz3 - jz0;
217
218             /* Calculate squared distance and things based on it */
219             rsq00            = dx00*dx00+dy00*dy00+dz00*dz00;
220             rsq10            = dx10*dx10+dy10*dy10+dz10*dz10;
221             rsq20            = dx20*dx20+dy20*dy20+dz20*dz20;
222             rsq30            = dx30*dx30+dy30*dy30+dz30*dz30;
223
224             rinv00           = gmx_invsqrt(rsq00);
225             rinv10           = gmx_invsqrt(rsq10);
226             rinv20           = gmx_invsqrt(rsq20);
227             rinv30           = gmx_invsqrt(rsq30);
228
229             rinvsq00         = rinv00*rinv00;
230             rinvsq10         = rinv10*rinv10;
231             rinvsq20         = rinv20*rinv20;
232             rinvsq30         = rinv30*rinv30;
233
234             /* Load parameters for j particles */
235             jq0              = charge[jnr+0];
236             vdwjidx0         = 2*vdwtype[jnr+0];
237
238             /**************************
239              * CALCULATE INTERACTIONS *
240              **************************/
241
242             if (rsq00<rcutoff2)
243             {
244
245             r00              = rsq00*rinv00;
246
247             c6_00            = vdwparam[vdwioffset0+vdwjidx0];
248             c12_00           = vdwparam[vdwioffset0+vdwjidx0+1];
249             c6grid_00        = vdwgridparam[vdwioffset0+vdwjidx0];
250
251             rinvsix          = rinvsq00*rinvsq00*rinvsq00;
252             ewcljrsq         = ewclj2*rsq00;
253             exponent         = exp(-ewcljrsq);
254             poly             = exponent*(1.0 + ewcljrsq + ewcljrsq*ewcljrsq*0.5);
255             vvdw6            = (c6_00-c6grid_00*(1.0-poly))*rinvsix;
256             vvdw12           = c12_00*rinvsix*rinvsix;
257             vvdw             = (vvdw12 - c12_00*sh_vdw_invrcut6*sh_vdw_invrcut6)*(1.0/12.0) - (vvdw6 - c6_00*sh_vdw_invrcut6 - c6grid_00*sh_lj_ewald)*(1.0/6.0);
258             fvdw             = (vvdw12 - vvdw6 - c6grid_00*(1.0/6.0)*exponent*ewclj6)*rinvsq00;
259
260             /* Update potential sums from outer loop */
261             vvdwsum         += vvdw;
262
263             fscal            = fvdw;
264
265             /* Calculate temporary vectorial force */
266             tx               = fscal*dx00;
267             ty               = fscal*dy00;
268             tz               = fscal*dz00;
269
270             /* Update vectorial force */
271             fix0            += tx;
272             fiy0            += ty;
273             fiz0            += tz;
274             f[j_coord_offset+DIM*0+XX] -= tx;
275             f[j_coord_offset+DIM*0+YY] -= ty;
276             f[j_coord_offset+DIM*0+ZZ] -= tz;
277
278             }
279
280             /**************************
281              * CALCULATE INTERACTIONS *
282              **************************/
283
284             if (rsq10<rcutoff2)
285             {
286
287             r10              = rsq10*rinv10;
288
289             qq10             = iq1*jq0;
290
291             /* EWALD ELECTROSTATICS */
292
293             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
294             ewrt             = r10*ewtabscale;
295             ewitab           = ewrt;
296             eweps            = ewrt-ewitab;
297             ewitab           = 4*ewitab;
298             felec            = ewtab[ewitab]+eweps*ewtab[ewitab+1];
299             velec            = qq10*((rinv10-sh_ewald)-(ewtab[ewitab+2]-ewtabhalfspace*eweps*(ewtab[ewitab]+felec)));
300             felec            = qq10*rinv10*(rinvsq10-felec);
301
302             /* Update potential sums from outer loop */
303             velecsum        += velec;
304
305             fscal            = felec;
306
307             /* Calculate temporary vectorial force */
308             tx               = fscal*dx10;
309             ty               = fscal*dy10;
310             tz               = fscal*dz10;
311
312             /* Update vectorial force */
313             fix1            += tx;
314             fiy1            += ty;
315             fiz1            += tz;
316             f[j_coord_offset+DIM*0+XX] -= tx;
317             f[j_coord_offset+DIM*0+YY] -= ty;
318             f[j_coord_offset+DIM*0+ZZ] -= tz;
319
320             }
321
322             /**************************
323              * CALCULATE INTERACTIONS *
324              **************************/
325
326             if (rsq20<rcutoff2)
327             {
328
329             r20              = rsq20*rinv20;
330
331             qq20             = iq2*jq0;
332
333             /* EWALD ELECTROSTATICS */
334
335             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
336             ewrt             = r20*ewtabscale;
337             ewitab           = ewrt;
338             eweps            = ewrt-ewitab;
339             ewitab           = 4*ewitab;
340             felec            = ewtab[ewitab]+eweps*ewtab[ewitab+1];
341             velec            = qq20*((rinv20-sh_ewald)-(ewtab[ewitab+2]-ewtabhalfspace*eweps*(ewtab[ewitab]+felec)));
342             felec            = qq20*rinv20*(rinvsq20-felec);
343
344             /* Update potential sums from outer loop */
345             velecsum        += velec;
346
347             fscal            = felec;
348
349             /* Calculate temporary vectorial force */
350             tx               = fscal*dx20;
351             ty               = fscal*dy20;
352             tz               = fscal*dz20;
353
354             /* Update vectorial force */
355             fix2            += tx;
356             fiy2            += ty;
357             fiz2            += tz;
358             f[j_coord_offset+DIM*0+XX] -= tx;
359             f[j_coord_offset+DIM*0+YY] -= ty;
360             f[j_coord_offset+DIM*0+ZZ] -= tz;
361
362             }
363
364             /**************************
365              * CALCULATE INTERACTIONS *
366              **************************/
367
368             if (rsq30<rcutoff2)
369             {
370
371             r30              = rsq30*rinv30;
372
373             qq30             = iq3*jq0;
374
375             /* EWALD ELECTROSTATICS */
376
377             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
378             ewrt             = r30*ewtabscale;
379             ewitab           = ewrt;
380             eweps            = ewrt-ewitab;
381             ewitab           = 4*ewitab;
382             felec            = ewtab[ewitab]+eweps*ewtab[ewitab+1];
383             velec            = qq30*((rinv30-sh_ewald)-(ewtab[ewitab+2]-ewtabhalfspace*eweps*(ewtab[ewitab]+felec)));
384             felec            = qq30*rinv30*(rinvsq30-felec);
385
386             /* Update potential sums from outer loop */
387             velecsum        += velec;
388
389             fscal            = felec;
390
391             /* Calculate temporary vectorial force */
392             tx               = fscal*dx30;
393             ty               = fscal*dy30;
394             tz               = fscal*dz30;
395
396             /* Update vectorial force */
397             fix3            += tx;
398             fiy3            += ty;
399             fiz3            += tz;
400             f[j_coord_offset+DIM*0+XX] -= tx;
401             f[j_coord_offset+DIM*0+YY] -= ty;
402             f[j_coord_offset+DIM*0+ZZ] -= tz;
403
404             }
405
406             /* Inner loop uses 181 flops */
407         }
408         /* End of innermost loop */
409
410         tx = ty = tz = 0;
411         f[i_coord_offset+DIM*0+XX] += fix0;
412         f[i_coord_offset+DIM*0+YY] += fiy0;
413         f[i_coord_offset+DIM*0+ZZ] += fiz0;
414         tx                         += fix0;
415         ty                         += fiy0;
416         tz                         += fiz0;
417         f[i_coord_offset+DIM*1+XX] += fix1;
418         f[i_coord_offset+DIM*1+YY] += fiy1;
419         f[i_coord_offset+DIM*1+ZZ] += fiz1;
420         tx                         += fix1;
421         ty                         += fiy1;
422         tz                         += fiz1;
423         f[i_coord_offset+DIM*2+XX] += fix2;
424         f[i_coord_offset+DIM*2+YY] += fiy2;
425         f[i_coord_offset+DIM*2+ZZ] += fiz2;
426         tx                         += fix2;
427         ty                         += fiy2;
428         tz                         += fiz2;
429         f[i_coord_offset+DIM*3+XX] += fix3;
430         f[i_coord_offset+DIM*3+YY] += fiy3;
431         f[i_coord_offset+DIM*3+ZZ] += fiz3;
432         tx                         += fix3;
433         ty                         += fiy3;
434         tz                         += fiz3;
435         fshift[i_shift_offset+XX]  += tx;
436         fshift[i_shift_offset+YY]  += ty;
437         fshift[i_shift_offset+ZZ]  += tz;
438
439         ggid                        = gid[iidx];
440         /* Update potential energies */
441         kernel_data->energygrp_elec[ggid] += velecsum;
442         kernel_data->energygrp_vdw[ggid] += vvdwsum;
443
444         /* Increment number of inner iterations */
445         inneriter                  += j_index_end - j_index_start;
446
447         /* Outer loop uses 41 flops */
448     }
449
450     /* Increment number of outer iterations */
451     outeriter        += nri;
452
453     /* Update outer/inner flops */
454
455     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_VDW_W4_VF,outeriter*41 + inneriter*181);
456 }
457 /*
458  * Gromacs nonbonded kernel:   nb_kernel_ElecEwSh_VdwLJEwSh_GeomW4P1_F_c
459  * Electrostatics interaction: Ewald
460  * VdW interaction:            LJEwald
461  * Geometry:                   Water4-Particle
462  * Calculate force/pot:        Force
463  */
464 void
465 nb_kernel_ElecEwSh_VdwLJEwSh_GeomW4P1_F_c
466                     (t_nblist                    * gmx_restrict       nlist,
467                      rvec                        * gmx_restrict          xx,
468                      rvec                        * gmx_restrict          ff,
469                      t_forcerec                  * gmx_restrict          fr,
470                      t_mdatoms                   * gmx_restrict     mdatoms,
471                      nb_kernel_data_t gmx_unused * gmx_restrict kernel_data,
472                      t_nrnb                      * gmx_restrict        nrnb)
473 {
474     int              i_shift_offset,i_coord_offset,j_coord_offset;
475     int              j_index_start,j_index_end;
476     int              nri,inr,ggid,iidx,jidx,jnr,outeriter,inneriter;
477     real             shX,shY,shZ,tx,ty,tz,fscal,rcutoff,rcutoff2;
478     int              *iinr,*jindex,*jjnr,*shiftidx,*gid;
479     real             *shiftvec,*fshift,*x,*f;
480     int              vdwioffset0;
481     real             ix0,iy0,iz0,fix0,fiy0,fiz0,iq0,isai0;
482     int              vdwioffset1;
483     real             ix1,iy1,iz1,fix1,fiy1,fiz1,iq1,isai1;
484     int              vdwioffset2;
485     real             ix2,iy2,iz2,fix2,fiy2,fiz2,iq2,isai2;
486     int              vdwioffset3;
487     real             ix3,iy3,iz3,fix3,fiy3,fiz3,iq3,isai3;
488     int              vdwjidx0;
489     real             jx0,jy0,jz0,fjx0,fjy0,fjz0,jq0,isaj0;
490     real             dx00,dy00,dz00,rsq00,rinv00,rinvsq00,r00,qq00,c6_00,c12_00,cexp1_00,cexp2_00;
491     real             dx10,dy10,dz10,rsq10,rinv10,rinvsq10,r10,qq10,c6_10,c12_10,cexp1_10,cexp2_10;
492     real             dx20,dy20,dz20,rsq20,rinv20,rinvsq20,r20,qq20,c6_20,c12_20,cexp1_20,cexp2_20;
493     real             dx30,dy30,dz30,rsq30,rinv30,rinvsq30,r30,qq30,c6_30,c12_30,cexp1_30,cexp2_30;
494     real             velec,felec,velecsum,facel,crf,krf,krf2;
495     real             *charge;
496     int              nvdwtype;
497     real             rinvsix,rvdw,vvdw,vvdw6,vvdw12,fvdw,fvdw6,fvdw12,vvdwsum,br,vvdwexp,sh_vdw_invrcut6;
498     int              *vdwtype;
499     real             *vdwparam;
500     real             c6grid_00;
501     real             c6grid_10;
502     real             c6grid_20;
503     real             c6grid_30;
504     real             ewclj,ewclj2,ewclj6,ewcljrsq,poly,exponent,sh_lj_ewald;
505     real             *vdwgridparam;
506     int              ewitab;
507     real             ewtabscale,eweps,sh_ewald,ewrt,ewtabhalfspace;
508     real             *ewtab;
509
510     x                = xx[0];
511     f                = ff[0];
512
513     nri              = nlist->nri;
514     iinr             = nlist->iinr;
515     jindex           = nlist->jindex;
516     jjnr             = nlist->jjnr;
517     shiftidx         = nlist->shift;
518     gid              = nlist->gid;
519     shiftvec         = fr->shift_vec[0];
520     fshift           = fr->fshift[0];
521     facel            = fr->epsfac;
522     charge           = mdatoms->chargeA;
523     nvdwtype         = fr->ntype;
524     vdwparam         = fr->nbfp;
525     vdwtype          = mdatoms->typeA;
526     vdwgridparam     = fr->ljpme_c6grid;
527     ewclj            = fr->ewaldcoeff_lj;
528     sh_lj_ewald      = fr->ic->sh_lj_ewald;
529     ewclj2           = ewclj*ewclj;
530     ewclj6           = ewclj2*ewclj2*ewclj2;
531
532     sh_ewald         = fr->ic->sh_ewald;
533     ewtab            = fr->ic->tabq_coul_F;
534     ewtabscale       = fr->ic->tabq_scale;
535     ewtabhalfspace   = 0.5/ewtabscale;
536
537     /* Setup water-specific parameters */
538     inr              = nlist->iinr[0];
539     iq1              = facel*charge[inr+1];
540     iq2              = facel*charge[inr+2];
541     iq3              = facel*charge[inr+3];
542     vdwioffset0      = 2*nvdwtype*vdwtype[inr+0];
543
544     /* When we use explicit cutoffs the value must be identical for elec and VdW, so use elec as an arbitrary choice */
545     rcutoff          = fr->rcoulomb;
546     rcutoff2         = rcutoff*rcutoff;
547
548     sh_vdw_invrcut6  = fr->ic->sh_invrc6;
549     rvdw             = fr->rvdw;
550
551     outeriter        = 0;
552     inneriter        = 0;
553
554     /* Start outer loop over neighborlists */
555     for(iidx=0; iidx<nri; iidx++)
556     {
557         /* Load shift vector for this list */
558         i_shift_offset   = DIM*shiftidx[iidx];
559         shX              = shiftvec[i_shift_offset+XX];
560         shY              = shiftvec[i_shift_offset+YY];
561         shZ              = shiftvec[i_shift_offset+ZZ];
562
563         /* Load limits for loop over neighbors */
564         j_index_start    = jindex[iidx];
565         j_index_end      = jindex[iidx+1];
566
567         /* Get outer coordinate index */
568         inr              = iinr[iidx];
569         i_coord_offset   = DIM*inr;
570
571         /* Load i particle coords and add shift vector */
572         ix0              = shX + x[i_coord_offset+DIM*0+XX];
573         iy0              = shY + x[i_coord_offset+DIM*0+YY];
574         iz0              = shZ + x[i_coord_offset+DIM*0+ZZ];
575         ix1              = shX + x[i_coord_offset+DIM*1+XX];
576         iy1              = shY + x[i_coord_offset+DIM*1+YY];
577         iz1              = shZ + x[i_coord_offset+DIM*1+ZZ];
578         ix2              = shX + x[i_coord_offset+DIM*2+XX];
579         iy2              = shY + x[i_coord_offset+DIM*2+YY];
580         iz2              = shZ + x[i_coord_offset+DIM*2+ZZ];
581         ix3              = shX + x[i_coord_offset+DIM*3+XX];
582         iy3              = shY + x[i_coord_offset+DIM*3+YY];
583         iz3              = shZ + x[i_coord_offset+DIM*3+ZZ];
584
585         fix0             = 0.0;
586         fiy0             = 0.0;
587         fiz0             = 0.0;
588         fix1             = 0.0;
589         fiy1             = 0.0;
590         fiz1             = 0.0;
591         fix2             = 0.0;
592         fiy2             = 0.0;
593         fiz2             = 0.0;
594         fix3             = 0.0;
595         fiy3             = 0.0;
596         fiz3             = 0.0;
597
598         /* Start inner kernel loop */
599         for(jidx=j_index_start; jidx<j_index_end; jidx++)
600         {
601             /* Get j neighbor index, and coordinate index */
602             jnr              = jjnr[jidx];
603             j_coord_offset   = DIM*jnr;
604
605             /* load j atom coordinates */
606             jx0              = x[j_coord_offset+DIM*0+XX];
607             jy0              = x[j_coord_offset+DIM*0+YY];
608             jz0              = x[j_coord_offset+DIM*0+ZZ];
609
610             /* Calculate displacement vector */
611             dx00             = ix0 - jx0;
612             dy00             = iy0 - jy0;
613             dz00             = iz0 - jz0;
614             dx10             = ix1 - jx0;
615             dy10             = iy1 - jy0;
616             dz10             = iz1 - jz0;
617             dx20             = ix2 - jx0;
618             dy20             = iy2 - jy0;
619             dz20             = iz2 - jz0;
620             dx30             = ix3 - jx0;
621             dy30             = iy3 - jy0;
622             dz30             = iz3 - jz0;
623
624             /* Calculate squared distance and things based on it */
625             rsq00            = dx00*dx00+dy00*dy00+dz00*dz00;
626             rsq10            = dx10*dx10+dy10*dy10+dz10*dz10;
627             rsq20            = dx20*dx20+dy20*dy20+dz20*dz20;
628             rsq30            = dx30*dx30+dy30*dy30+dz30*dz30;
629
630             rinv00           = gmx_invsqrt(rsq00);
631             rinv10           = gmx_invsqrt(rsq10);
632             rinv20           = gmx_invsqrt(rsq20);
633             rinv30           = gmx_invsqrt(rsq30);
634
635             rinvsq00         = rinv00*rinv00;
636             rinvsq10         = rinv10*rinv10;
637             rinvsq20         = rinv20*rinv20;
638             rinvsq30         = rinv30*rinv30;
639
640             /* Load parameters for j particles */
641             jq0              = charge[jnr+0];
642             vdwjidx0         = 2*vdwtype[jnr+0];
643
644             /**************************
645              * CALCULATE INTERACTIONS *
646              **************************/
647
648             if (rsq00<rcutoff2)
649             {
650
651             r00              = rsq00*rinv00;
652
653             c6_00            = vdwparam[vdwioffset0+vdwjidx0];
654             c12_00           = vdwparam[vdwioffset0+vdwjidx0+1];
655             c6grid_00        = vdwgridparam[vdwioffset0+vdwjidx0];
656
657             rinvsix          = rinvsq00*rinvsq00*rinvsq00;
658             ewcljrsq         = ewclj2*rsq00;
659             exponent         = exp(-ewcljrsq);
660             poly             = exponent*(1.0 + ewcljrsq + ewcljrsq*ewcljrsq*0.5);
661             fvdw             = (((c12_00*rinvsix - c6_00 + c6grid_00*(1.0-poly))*rinvsix) - c6grid_00*(1.0/6.0)*exponent*ewclj6)*rinvsq00;
662
663             fscal            = fvdw;
664
665             /* Calculate temporary vectorial force */
666             tx               = fscal*dx00;
667             ty               = fscal*dy00;
668             tz               = fscal*dz00;
669
670             /* Update vectorial force */
671             fix0            += tx;
672             fiy0            += ty;
673             fiz0            += tz;
674             f[j_coord_offset+DIM*0+XX] -= tx;
675             f[j_coord_offset+DIM*0+YY] -= ty;
676             f[j_coord_offset+DIM*0+ZZ] -= tz;
677
678             }
679
680             /**************************
681              * CALCULATE INTERACTIONS *
682              **************************/
683
684             if (rsq10<rcutoff2)
685             {
686
687             r10              = rsq10*rinv10;
688
689             qq10             = iq1*jq0;
690
691             /* EWALD ELECTROSTATICS */
692
693             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
694             ewrt             = r10*ewtabscale;
695             ewitab           = ewrt;
696             eweps            = ewrt-ewitab;
697             felec            = (1.0-eweps)*ewtab[ewitab]+eweps*ewtab[ewitab+1];
698             felec            = qq10*rinv10*(rinvsq10-felec);
699
700             fscal            = felec;
701
702             /* Calculate temporary vectorial force */
703             tx               = fscal*dx10;
704             ty               = fscal*dy10;
705             tz               = fscal*dz10;
706
707             /* Update vectorial force */
708             fix1            += tx;
709             fiy1            += ty;
710             fiz1            += tz;
711             f[j_coord_offset+DIM*0+XX] -= tx;
712             f[j_coord_offset+DIM*0+YY] -= ty;
713             f[j_coord_offset+DIM*0+ZZ] -= tz;
714
715             }
716
717             /**************************
718              * CALCULATE INTERACTIONS *
719              **************************/
720
721             if (rsq20<rcutoff2)
722             {
723
724             r20              = rsq20*rinv20;
725
726             qq20             = iq2*jq0;
727
728             /* EWALD ELECTROSTATICS */
729
730             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
731             ewrt             = r20*ewtabscale;
732             ewitab           = ewrt;
733             eweps            = ewrt-ewitab;
734             felec            = (1.0-eweps)*ewtab[ewitab]+eweps*ewtab[ewitab+1];
735             felec            = qq20*rinv20*(rinvsq20-felec);
736
737             fscal            = felec;
738
739             /* Calculate temporary vectorial force */
740             tx               = fscal*dx20;
741             ty               = fscal*dy20;
742             tz               = fscal*dz20;
743
744             /* Update vectorial force */
745             fix2            += tx;
746             fiy2            += ty;
747             fiz2            += tz;
748             f[j_coord_offset+DIM*0+XX] -= tx;
749             f[j_coord_offset+DIM*0+YY] -= ty;
750             f[j_coord_offset+DIM*0+ZZ] -= tz;
751
752             }
753
754             /**************************
755              * CALCULATE INTERACTIONS *
756              **************************/
757
758             if (rsq30<rcutoff2)
759             {
760
761             r30              = rsq30*rinv30;
762
763             qq30             = iq3*jq0;
764
765             /* EWALD ELECTROSTATICS */
766
767             /* Calculate Ewald table index by multiplying r with scale and truncate to integer */
768             ewrt             = r30*ewtabscale;
769             ewitab           = ewrt;
770             eweps            = ewrt-ewitab;
771             felec            = (1.0-eweps)*ewtab[ewitab]+eweps*ewtab[ewitab+1];
772             felec            = qq30*rinv30*(rinvsq30-felec);
773
774             fscal            = felec;
775
776             /* Calculate temporary vectorial force */
777             tx               = fscal*dx30;
778             ty               = fscal*dy30;
779             tz               = fscal*dz30;
780
781             /* Update vectorial force */
782             fix3            += tx;
783             fiy3            += ty;
784             fiz3            += tz;
785             f[j_coord_offset+DIM*0+XX] -= tx;
786             f[j_coord_offset+DIM*0+YY] -= ty;
787             f[j_coord_offset+DIM*0+ZZ] -= tz;
788
789             }
790
791             /* Inner loop uses 146 flops */
792         }
793         /* End of innermost loop */
794
795         tx = ty = tz = 0;
796         f[i_coord_offset+DIM*0+XX] += fix0;
797         f[i_coord_offset+DIM*0+YY] += fiy0;
798         f[i_coord_offset+DIM*0+ZZ] += fiz0;
799         tx                         += fix0;
800         ty                         += fiy0;
801         tz                         += fiz0;
802         f[i_coord_offset+DIM*1+XX] += fix1;
803         f[i_coord_offset+DIM*1+YY] += fiy1;
804         f[i_coord_offset+DIM*1+ZZ] += fiz1;
805         tx                         += fix1;
806         ty                         += fiy1;
807         tz                         += fiz1;
808         f[i_coord_offset+DIM*2+XX] += fix2;
809         f[i_coord_offset+DIM*2+YY] += fiy2;
810         f[i_coord_offset+DIM*2+ZZ] += fiz2;
811         tx                         += fix2;
812         ty                         += fiy2;
813         tz                         += fiz2;
814         f[i_coord_offset+DIM*3+XX] += fix3;
815         f[i_coord_offset+DIM*3+YY] += fiy3;
816         f[i_coord_offset+DIM*3+ZZ] += fiz3;
817         tx                         += fix3;
818         ty                         += fiy3;
819         tz                         += fiz3;
820         fshift[i_shift_offset+XX]  += tx;
821         fshift[i_shift_offset+YY]  += ty;
822         fshift[i_shift_offset+ZZ]  += tz;
823
824         /* Increment number of inner iterations */
825         inneriter                  += j_index_end - j_index_start;
826
827         /* Outer loop uses 39 flops */
828     }
829
830     /* Increment number of outer iterations */
831     outeriter        += nri;
832
833     /* Update outer/inner flops */
834
835     inc_nrnb(nrnb,eNR_NBKERNEL_ELEC_VDW_W4_F,outeriter*39 + inneriter*146);
836 }