Merge remote-tracking branch 'origin/release-4-6'
[alexxy/gromacs.git] / src / gromacs / gmxlib / nonbonded / nb_generic_adress.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_adress.h"
45
46 #define ALMOST_ZERO 1e-30
47 #define ALMOST_ONE 1-(1e-30)
48 void
49 gmx_nb_generic_adress_kernel(t_nblist *           nlist,
50                                           t_forcerec *         fr,
51                                           t_mdatoms *          mdatoms,
52                                           real *               x,
53                                           real *               f,
54                                           real *               fshift,
55                                           real *               Vc,
56                                           real *               Vvdw,
57                                           real                 tabscale,
58                                           real *               VFtab,
59                                           int *                outeriter,
60                                           int *                inneriter,
61                                           gmx_bool                bCG)
62 {
63     int           nri,ntype,table_nelements,icoul,ivdw;
64     real          facel,gbtabscale;
65     int           n,ii,is3,ii3,k,nj0,nj1,jnr,j3,ggid,nnn,n0;
66     real          shX,shY,shZ;
67     real          fscal,tx,ty,tz;
68     real          rinvsq;
69     real          iq;
70     real          qq,vcoul,krsq,vctot;
71     int           nti,nvdwparam;
72     int           tj;
73     real          rt,r,eps,eps2,Y,F,Geps,Heps2,VV,FF,Fp,fijD,fijR;
74     real          rinvsix;
75     real          Vvdwtot;
76     real          Vvdw_rep,Vvdw_disp;
77     real          ix,iy,iz,fix,fiy,fiz;
78     real          jx,jy,jz;
79     real          dx,dy,dz,rsq,rinv;
80     real          c6,c12,cexp1,cexp2,br;
81     real *        charge;
82     real *        shiftvec;
83     real *        vdwparam;
84     int *         shift;
85     int *         type;
86
87     real *     wf;
88     real       weight_cg1;
89     real       weight_cg2;
90     real       weight_product;
91     real       hybscal; /* the multiplicator to the force for hybrid interactions*/
92     gmx_bool   bHybrid; /*Are we in the hybrid zone ?*/
93     real       force_cap;
94
95     wf                  = mdatoms->wf;
96
97     force_cap = fr->adress_ex_forcecap;
98
99     icoul               = nlist->icoul;
100     ivdw                = nlist->ivdw;
101
102     /* avoid compiler warnings for cases that cannot happen */
103     nnn                 = 0;
104     vcoul               = 0.0;
105     eps                 = 0.0;
106     eps2                = 0.0;
107
108     /* 3 VdW parameters for buckingham, otherwise 2 */
109     nvdwparam           = (nlist->ivdw==2) ? 3 : 2;
110     table_nelements     = (icoul==3) ? 4 : 0;
111     table_nelements    += (ivdw==3) ? 8 : 0;
112
113     charge              = mdatoms->chargeA;
114     type                = mdatoms->typeA;
115     facel               = fr->epsfac;
116     shiftvec            = fr->shift_vec[0];
117     vdwparam            = fr->nbfp;
118     ntype               = fr->ntype;
119
120
121
122
123    for(n=0; (n<nlist->nri); n++)
124     {
125         is3              = 3*nlist->shift[n];
126         shX              = shiftvec[is3];
127         shY              = shiftvec[is3+1];
128         shZ              = shiftvec[is3+2];
129         nj0              = nlist->jindex[n];
130         nj1              = nlist->jindex[n+1];
131         ii               = nlist->iinr[n];
132         ii3              = 3*ii;
133         ix               = shX + x[ii3+0];
134         iy               = shY + x[ii3+1];
135         iz               = shZ + x[ii3+2];
136         iq               = facel*charge[ii];
137         nti              = nvdwparam*ntype*type[ii];
138         vctot            = 0;
139         Vvdwtot          = 0;
140         fix              = 0;
141         fiy              = 0;
142         fiz              = 0;
143
144         weight_cg1       = wf[ii];
145
146         /* TODO: why does this line her not speed up things ?
147          * if ((!bCG) && weight_cg1 < ALMOST_ZERO) continue;
148          */
149         for(k=nj0; (k<nj1); k++)
150         {
151             jnr              = nlist->jjnr[k];
152             weight_cg2       = wf[jnr];
153
154             weight_product   = weight_cg1*weight_cg2;
155
156             if (weight_product < ALMOST_ZERO)
157             {                
158                 /* if it's a explicit loop, skip this atom */
159                 if (!bCG)
160                 {
161                     continue;
162                 }
163                 else /* if it's a coarse grained loop, include this atom */
164                 {
165                     bHybrid = FALSE;
166                     hybscal = 1.0;
167                 }
168             }
169             else if (weight_product >= ALMOST_ONE)
170             {
171                 
172                 /* if it's a explicit loop, include this atom */
173                 if(!bCG)
174                 {
175                     bHybrid = FALSE;
176                     hybscal = 1.0;
177                 }             
178                 else  /* if it's a coarse grained loop, skip this atom */
179                 {
180                     continue;
181                 }
182             }
183             /* both have double identity, get hybrid scaling factor */
184             else
185             {
186                 bHybrid = TRUE;                       
187                 hybscal = weight_product;
188
189                 if(bCG)
190                 {
191                     hybscal = 1.0 - hybscal;
192                 }
193             }
194
195             
196             j3               = 3*jnr;
197             jx               = x[j3+0];
198             jy               = x[j3+1];
199             jz               = x[j3+2];
200             dx               = ix - jx;
201             dy               = iy - jy;
202             dz               = iz - jz;
203             rsq              = dx*dx+dy*dy+dz*dz;
204             rinv             = gmx_invsqrt(rsq);
205             rinvsq           = rinv*rinv;
206
207
208                         fscal            = 0;
209
210                         if(icoul==3 || ivdw==3)
211                         {
212                                 r                = rsq*rinv;
213                                 rt               = r*tabscale;
214                                 n0               = rt;
215                                 eps              = rt-n0;
216                                 eps2             = eps*eps;
217                                 nnn              = table_nelements*n0;
218                         }
219
220                         /* Coulomb interaction. icoul==0 means no interaction */
221                         if(icoul>0)
222                         {
223                                 qq               = iq*charge[jnr];
224
225                                 switch(icoul)
226                                 {
227                                         case 1:
228                                                 /* Vanilla cutoff coulomb */
229                                                 vcoul            = qq*rinv;
230                                                 fscal            = vcoul*rinvsq;
231                                                 break;
232
233                                         case 2:
234                                                 /* Reaction-field */
235                                                 krsq             = fr->k_rf*rsq;
236                                                 vcoul            = qq*(rinv+krsq-fr->c_rf);
237                                                 fscal            = qq*(rinv-2.0*krsq)*rinvsq;
238                                                 break;
239
240                                         case 3:
241                                                 /* Tabulated coulomb */
242                                                 Y                = VFtab[nnn];
243                                                 F                = VFtab[nnn+1];
244                                                 Geps             = eps*VFtab[nnn+2];
245                                                 Heps2            = eps2*VFtab[nnn+3];
246                                                 nnn             += 4;
247                                                 Fp               = F+Geps+Heps2;
248                                                 VV               = Y+eps*Fp;
249                                                 FF               = Fp+Geps+2.0*Heps2;
250                                                 vcoul            = qq*VV;
251                                                 fscal            = -qq*FF*tabscale*rinv;
252                                                 break;
253
254                                         case 4:
255                                                 /* GB */
256                                                 gmx_fatal(FARGS,"Death & horror! GB generic interaction not implemented.\n");
257                                                 break;
258
259                                         default:
260                                                 gmx_fatal(FARGS,"Death & horror! No generic coulomb interaction for icoul=%d.\n",icoul);
261                                                 break;
262                                 }
263                                 vctot            = vctot+vcoul;
264                         } /* End of coulomb interactions */
265
266
267                         /* VdW interaction. ivdw==0 means no interaction */
268                         if(ivdw>0)
269                         {
270                                 tj               = nti+nvdwparam*type[jnr];
271
272                                 switch(ivdw)
273                                 {
274                                         case 1:
275                                                 /* Vanilla Lennard-Jones cutoff */
276                                                 c6               = vdwparam[tj];
277                                                 c12              = vdwparam[tj+1];
278
279                                                 rinvsix          = rinvsq*rinvsq*rinvsq;
280                                                 Vvdw_disp        = c6*rinvsix;
281                                                 Vvdw_rep         = c12*rinvsix*rinvsix;
282                                                 fscal           += (12.0*Vvdw_rep-6.0*Vvdw_disp)*rinvsq;
283                                                 Vvdwtot          = Vvdwtot+Vvdw_rep-Vvdw_disp;
284                                                 break;
285
286                                         case 2:
287                                                 /* Buckingham */
288                                                 c6               = vdwparam[tj];
289                                                 cexp1            = vdwparam[tj+1];
290                                                 cexp2            = vdwparam[tj+2];
291
292                                                 rinvsix          = rinvsq*rinvsq*rinvsq;
293                                                 Vvdw_disp        = c6*rinvsix;
294                                                 br               = cexp2*rsq*rinv;
295                                                 Vvdw_rep         = cexp1*exp(-br);
296                                                 fscal           += (br*Vvdw_rep-6.0*Vvdw_disp)*rinvsq;
297                                                 Vvdwtot          = Vvdwtot+Vvdw_rep-Vvdw_disp;
298                                                 break;
299
300                                         case 3:
301                                                 /* Tabulated VdW */
302                                                 c6               = vdwparam[tj];
303                                                 c12              = vdwparam[tj+1];
304
305                                                 Y                = VFtab[nnn];
306                                                 F                = VFtab[nnn+1];
307                                                 Geps             = eps*VFtab[nnn+2];
308                                                 Heps2            = eps2*VFtab[nnn+3];
309                                                 Fp               = F+Geps+Heps2;
310                                                 VV               = Y+eps*Fp;
311                                                 FF               = Fp+Geps+2.0*Heps2;
312                                                 Vvdw_disp        = c6*VV;
313                                                 fijD             = c6*FF;
314                                                 nnn             += 4;
315                                                 Y                = VFtab[nnn];
316                                                 F                = VFtab[nnn+1];
317                                                 Geps             = eps*VFtab[nnn+2];
318                                                 Heps2            = eps2*VFtab[nnn+3];
319                                                 Fp               = F+Geps+Heps2;
320                                                 VV               = Y+eps*Fp;
321                                                 FF               = Fp+Geps+2.0*Heps2;
322                                                 Vvdw_rep         = c12*VV;
323                                                 fijR             = c12*FF;
324                                                 fscal           += -(fijD+fijR)*tabscale*rinv;
325                                                 Vvdwtot          = Vvdwtot + Vvdw_disp + Vvdw_rep;
326                                                 if(!bCG && force_cap>0 && (fabs(fscal)> force_cap))
327                                                 {
328                                                      fscal=force_cap*fscal/fabs(fscal);
329                                                 }
330                                                 break;
331
332                                         default:
333                                                 gmx_fatal(FARGS,"Death & horror! No generic VdW interaction for ivdw=%d.\n",ivdw);
334                                                 break;
335                                 }
336                         } /* end VdW interactions */
337
338              /* force weight is one anyway */
339                     if (bHybrid)
340                     {
341                         fscal *= hybscal;
342                     }
343                         
344             tx               = fscal*dx;
345             ty               = fscal*dy;
346             tz               = fscal*dz;
347             fix              = fix + tx;
348             fiy              = fiy + ty;
349             fiz              = fiz + tz;
350             f[j3+0]          = f[j3+0] - tx;
351             f[j3+1]          = f[j3+1] - ty;
352             f[j3+2]          = f[j3+2] - tz;
353         }
354
355         f[ii3+0]         = f[ii3+0] + fix;
356         f[ii3+1]         = f[ii3+1] + fiy;
357         f[ii3+2]         = f[ii3+2] + fiz;
358         fshift[is3]      = fshift[is3]+fix;
359         fshift[is3+1]    = fshift[is3+1]+fiy;
360         fshift[is3+2]    = fshift[is3+2]+fiz;
361         ggid             = nlist->gid[n];
362         Vc[ggid]         = Vc[ggid] + vctot;
363         Vvdw[ggid]       = Vvdw[ggid] + Vvdwtot;
364     }
365
366     *outeriter       = nlist->nri;
367     *inneriter       = nlist->jindex[n];
368 }
369