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