Merge remote-tracking branch 'origin/release-4-6'
[alexxy/gromacs.git] / src / gromacs / gmxlib / nonbonded / nb_generic.c
1 /*
2  * 
3  *                This source code is part of
4  * 
5  *                 G   R   O   M   A   C   S
6  * 
7  *          GROningen MAchine for Chemical Simulations
8  * 
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  * 
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * GROningen Mixture of Alchemy and Childrens' Stories
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include <math.h>
40
41 #include "types/simple.h"
42 #include "vec.h"
43 #include "typedefs.h"
44 #include "nb_generic.h"
45
46 void
47 gmx_nb_generic_kernel(t_nblist *           nlist,
48                                           t_forcerec *         fr,
49                                           t_mdatoms *          mdatoms,
50                                           real *               x,
51                                           real *               f,
52                                           real *               fshift,
53                                           real *               Vc,
54                                           real *               Vvdw,
55                                           real                 tabscale,  
56                                           real *               VFtab,
57                                           int *                outeriter,
58                                           int *                inneriter)
59 {
60     int           nri,ntype,table_nelements,icoul,ivdw;
61     real          facel,gbtabscale;
62     int           n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid,nnn,n0;
63     real          shX,shY,shZ;
64     real          fscal,tx,ty,tz;
65     real          rinvsq;
66     real          iq;
67     real          qq,vcoul,krsq,vctot;
68     int           nti,nvdwparam;
69     int           tj;
70         real          rt,r,eps,eps2,Y,F,Geps,Heps2,VV,FF,Fp,fijD,fijR;
71     real          rinvsix;
72     real          Vvdwtot;
73     real          Vvdw_rep,Vvdw_disp;
74     real          ix,iy,iz,fix,fiy,fiz;
75     real          jx,jy,jz;
76     real          dx,dy,dz,rsq,rinv;
77     real          c6,c12,cexp1,cexp2,br;
78         real *        charge;
79         real *        shiftvec;
80         real *        vdwparam;
81         int *         shift;
82         int *         type;
83         
84         icoul               = nlist->icoul;
85         ivdw                = nlist->ivdw;
86
87         /* avoid compiler warnings for cases that cannot happen */
88         nnn                 = 0;
89         vcoul               = 0.0;
90         eps                 = 0.0;
91         eps2                = 0.0;
92         
93         /* 3 VdW parameters for buckingham, otherwise 2 */
94         nvdwparam           = (nlist->ivdw==2) ? 3 : 2;
95         table_nelements     = (icoul==3) ? 4 : 0;
96         table_nelements    += (ivdw==3) ? 8 : 0;
97           
98     charge              = mdatoms->chargeA;
99         type                = mdatoms->typeA;
100         facel               = fr->epsfac;
101         shiftvec            = fr->shift_vec[0];
102         vdwparam            = fr->nbfp;
103         ntype               = fr->ntype;
104         
105         for(n=0; (n<nlist->nri); n++)
106     {
107         is3              = 3*nlist->shift[n];     
108         shX              = shiftvec[is3];  
109         shY              = shiftvec[is3+1];
110         shZ              = shiftvec[is3+2];
111         nj0              = nlist->jindex[n];      
112         nj1              = nlist->jindex[n+1];    
113         ii               = nlist->iinr[n];        
114         ii3              = 3*ii;           
115         ix               = shX + x[ii3+0];
116         iy               = shY + x[ii3+1];
117         iz               = shZ + x[ii3+2];
118         iq               = facel*charge[ii];
119         nti              = nvdwparam*ntype*type[ii];
120         vctot            = 0;              
121         Vvdwtot          = 0;              
122         fix              = 0;              
123         fiy              = 0;              
124         fiz              = 0;              
125         
126         for(k=nj0; (k<nj1); k++)
127         {
128             jnr              = nlist->jjnr[k];        
129             j3               = 3*jnr;          
130             jx               = x[j3+0];      
131             jy               = x[j3+1];      
132             jz               = x[j3+2];      
133             dx               = ix - jx;      
134             dy               = iy - jy;      
135             dz               = iz - jz;      
136             rsq              = dx*dx+dy*dy+dz*dz;
137             rinv             = gmx_invsqrt(rsq);
138             rinvsq           = rinv*rinv;  
139                         fscal            = 0;
140                         
141                         if(icoul==3 || ivdw==3)
142                         {
143                                 r                = rsq*rinv;
144                                 rt               = r*tabscale;     
145                                 n0               = rt;             
146                                 eps              = rt-n0;          
147                                 eps2             = eps*eps;        
148                                 nnn              = table_nelements*n0;                                          
149                         }
150                         
151                         /* Coulomb interaction. icoul==0 means no interaction */
152                         if(icoul>0)
153                         {
154                                 qq               = iq*charge[jnr]; 
155
156                                 switch(icoul)
157                                 {
158                                         case 1:
159                                                 /* Vanilla cutoff coulomb */
160                                                 vcoul            = qq*rinv;      
161                                                 fscal            = vcoul*rinvsq; 
162                                                 break;
163
164                                         case 2:
165                                                 /* Reaction-field */
166                                                 krsq             = fr->k_rf*rsq;      
167                                                 vcoul            = qq*(rinv+krsq-fr->c_rf);
168                                                 fscal            = qq*(rinv-2.0*krsq)*rinvsq;
169                                                 break;
170
171                                         case 3:
172                                                 /* Tabulated coulomb */
173                                                 Y                = VFtab[nnn];     
174                                                 F                = VFtab[nnn+1];   
175                                                 Geps             = eps*VFtab[nnn+2];
176                                                 Heps2            = eps2*VFtab[nnn+3];
177                                                 nnn             += 4;
178                                                 Fp               = F+Geps+Heps2;   
179                                                 VV               = Y+eps*Fp;       
180                                                 FF               = Fp+Geps+2.0*Heps2;
181                                                 vcoul            = qq*VV;          
182                                                 fscal            = -qq*FF*tabscale*rinv;
183                                                 break;
184                                         
185                                         case 4:
186                                                 /* GB */
187                                                 gmx_fatal(FARGS,"Death & horror! GB generic interaction not implemented.\n");
188                                                 break;
189                                         
190                                         default:
191                                                 gmx_fatal(FARGS,"Death & horror! No generic coulomb interaction for icoul=%d.\n",icoul);
192                                                 break;
193                                 }
194                                 vctot            = vctot+vcoul;    
195                         } /* End of coulomb interactions */
196                         
197                         
198                         /* VdW interaction. ivdw==0 means no interaction */
199                         if(ivdw>0)
200                         {
201                                 tj               = nti+nvdwparam*type[jnr];
202                                 
203                                 switch(ivdw)
204                                 {
205                                         case 1:
206                                                 /* Vanilla Lennard-Jones cutoff */
207                                                 c6               = vdwparam[tj];   
208                                                 c12              = vdwparam[tj+1]; 
209                                                 
210                                                 rinvsix          = rinvsq*rinvsq*rinvsq;
211                                                 Vvdw_disp        = c6*rinvsix;     
212                                                 Vvdw_rep         = c12*rinvsix*rinvsix;
213                                                 fscal           += (12.0*Vvdw_rep-6.0*Vvdw_disp)*rinvsq;
214                                                 Vvdwtot          = Vvdwtot+Vvdw_rep-Vvdw_disp;
215                                                 break;
216                                                 
217                                         case 2:
218                                                 /* Buckingham */
219                                                 c6               = vdwparam[tj];   
220                                                 cexp1            = vdwparam[tj+1]; 
221                                                 cexp2            = vdwparam[tj+2]; 
222                                                 
223                                                 rinvsix          = rinvsq*rinvsq*rinvsq;
224                                                 Vvdw_disp        = c6*rinvsix;     
225                                                 br               = cexp2*rsq*rinv;
226                                                 Vvdw_rep         = cexp1*exp(-br); 
227                                                 fscal           += (br*Vvdw_rep-6.0*Vvdw_disp)*rinvsq;
228                                                 Vvdwtot          = Vvdwtot+Vvdw_rep-Vvdw_disp;
229                                                 break;
230                                                 
231                                         case 3:
232                                                 /* Tabulated VdW */
233                                                 c6               = vdwparam[tj];   
234                                                 c12              = vdwparam[tj+1]; 
235
236                                                 Y                = VFtab[nnn];     
237                                                 F                = VFtab[nnn+1];   
238                                                 Geps             = eps*VFtab[nnn+2];
239                                                 Heps2            = eps2*VFtab[nnn+3];
240                                                 Fp               = F+Geps+Heps2;   
241                                                 VV               = Y+eps*Fp;       
242                                                 FF               = Fp+Geps+2.0*Heps2;
243                                                 Vvdw_disp        = c6*VV;          
244                                                 fijD             = c6*FF;          
245                                                 nnn             += 4;          
246                                                 Y                = VFtab[nnn];     
247                                                 F                = VFtab[nnn+1];   
248                                                 Geps             = eps*VFtab[nnn+2];
249                                                 Heps2            = eps2*VFtab[nnn+3];
250                                                 Fp               = F+Geps+Heps2;   
251                                                 VV               = Y+eps*Fp;       
252                                                 FF               = Fp+Geps+2.0*Heps2;
253                                                 Vvdw_rep         = c12*VV;         
254                                                 fijR             = c12*FF;         
255                                                 fscal           += -(fijD+fijR)*tabscale*rinv;
256                                                 Vvdwtot          = Vvdwtot + Vvdw_disp + Vvdw_rep;                                              
257                                                 break;
258                                                                                                 
259                                         default:
260                                                 gmx_fatal(FARGS,"Death & horror! No generic VdW interaction for ivdw=%d.\n",ivdw);
261                                                 break;
262                                 }
263                         } /* end VdW interactions */
264                         
265                         
266             tx               = fscal*dx;     
267             ty               = fscal*dy;     
268             tz               = fscal*dz;     
269             fix              = fix + tx;      
270             fiy              = fiy + ty;      
271             fiz              = fiz + tz;      
272             f[j3+0]          = f[j3+0] - tx;
273             f[j3+1]          = f[j3+1] - ty;
274             f[j3+2]          = f[j3+2] - tz;
275         }
276         
277         f[ii3+0]         = f[ii3+0] + fix;
278         f[ii3+1]         = f[ii3+1] + fiy;
279         f[ii3+2]         = f[ii3+2] + fiz;
280         fshift[is3]      = fshift[is3]+fix;
281         fshift[is3+1]    = fshift[is3+1]+fiy;
282         fshift[is3+2]    = fshift[is3+2]+fiz;
283         ggid             = nlist->gid[n];         
284         Vc[ggid]         = Vc[ggid] + vctot;
285         Vvdw[ggid]       = Vvdw[ggid] + Vvdwtot;
286     }
287     
288     *outeriter       = nlist->nri;            
289     *inneriter       = nlist->jindex[n];                
290 }
291