Merge branch release-4-6
[alexxy/gromacs.git] / src / gromacs / mdlib / wall.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  * 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-2008, 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  * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <math.h>
41 #include <string.h>
42 #include "maths.h"
43 #include "sysstuff.h"
44 #include "typedefs.h"
45 #include "macros.h"
46 #include "smalloc.h"
47 #include "force.h"
48 #include "gromacs/fileio/filenm.h"
49 #include "nrnb.h"
50 #include "vec.h"
51
52 void make_wall_tables(FILE *fplog, const output_env_t oenv,
53                       const t_inputrec *ir, const char *tabfn,
54                       const gmx_groups_t *groups,
55                       t_forcerec *fr)
56 {
57     int           w, negp_pp, egp, i, j;
58     int          *nm_ind;
59     char          buf[STRLEN];
60     t_forcetable *tab;
61
62     negp_pp = ir->opts.ngener - ir->nwall;
63     nm_ind  = groups->grps[egcENER].nm_ind;
64
65     if (fplog)
66     {
67         fprintf(fplog, "Reading user tables for %d energy groups with %d walls\n",
68                 negp_pp, ir->nwall);
69     }
70
71     snew(fr->wall_tab, ir->nwall);
72     for (w = 0; w < ir->nwall; w++)
73     {
74         snew(fr->wall_tab[w], negp_pp);
75         for (egp = 0; egp < negp_pp; egp++)
76         {
77             /* If the energy group pair is excluded, we don't need a table */
78             if (!(fr->egp_flags[egp*ir->opts.ngener+negp_pp+w] & EGP_EXCL))
79             {
80                 tab = &fr->wall_tab[w][egp];
81                 sprintf(buf, "%s", tabfn);
82                 sprintf(buf + strlen(tabfn) - strlen(ftp2ext(efXVG)) - 1, "_%s_%s.%s",
83                         *groups->grpname[nm_ind[egp]],
84                         *groups->grpname[nm_ind[negp_pp+w]],
85                         ftp2ext(efXVG));
86                 *tab = make_tables(fplog, oenv, fr, FALSE, buf, 0, GMX_MAKETABLES_FORCEUSER);
87                 /* Since wall have no charge, we can compress the table */
88                 for (i = 0; i <= tab->n; i++)
89                 {
90                     for (j = 0; j < 8; j++)
91                     {
92                         tab->data[8*i+j] = tab->data[12*i+4+j];
93                     }
94                 }
95             }
96         }
97     }
98 }
99
100 static void wall_error(int a, rvec *x, real r)
101 {
102     gmx_fatal(FARGS,
103               "An atom is beyond the wall: coordinates %f %f %f, distance %f\n"
104               "You might want to use the mdp option wall_r_linpot",
105               x[a][XX], x[a][YY], x[a][ZZ], r);
106 }
107
108 real do_walls(t_inputrec *ir, t_forcerec *fr, matrix box, t_mdatoms *md,
109               rvec x[], rvec f[], real lambda, real Vlj[], t_nrnb *nrnb)
110 {
111     int             nwall, w, lam, i;
112     int             ntw[2], at, ntype, ngid, ggid, *egp_flags, *type;
113     real           *nbfp, lamfac, fac_d[2], fac_r[2], Cd, Cr, Vtot, Fwall[2];
114     real            wall_z[2], r, mr, r1, r2, r4, Vd, Vr, V = 0, Fd, Fr, F = 0, dvdlambda;
115     dvec            xf_z;
116     int             n0, nnn;
117     real            tabscale, *VFtab, rt, eps, eps2, Yt, Ft, Geps, Heps, Heps2, Fp, VV, FF;
118     unsigned short *gid = md->cENER;
119     t_forcetable   *tab;
120
121     nwall     = ir->nwall;
122     ngid      = ir->opts.ngener;
123     ntype     = fr->ntype;
124     nbfp      = fr->nbfp;
125     egp_flags = fr->egp_flags;
126
127     for (w = 0; w < nwall; w++)
128     {
129         ntw[w] = 2*ntype*ir->wall_atomtype[w];
130         switch (ir->wall_type)
131         {
132             case ewt93:
133                 fac_d[w] = ir->wall_density[w]*M_PI/6;
134                 fac_r[w] = ir->wall_density[w]*M_PI/45;
135                 break;
136             case ewt104:
137                 fac_d[w] = ir->wall_density[w]*M_PI/2;
138                 fac_r[w] = ir->wall_density[w]*M_PI/5;
139                 break;
140             default:
141                 break;
142         }
143         Fwall[w] = 0;
144     }
145     wall_z[0] = 0;
146     wall_z[1] = box[ZZ][ZZ];
147
148     Vtot      = 0;
149     dvdlambda = 0;
150     clear_dvec(xf_z);
151     for (lam = 0; lam < (md->nPerturbed ? 2 : 1); lam++)
152     {
153         if (md->nPerturbed)
154         {
155             if (lam == 0)
156             {
157                 lamfac = 1 - lambda;
158                 type   = md->typeA;
159             }
160             else
161             {
162                 lamfac = 0;
163                 type   = md->typeB;
164             }
165         }
166         else
167         {
168             lamfac = 1;
169             type   = md->typeA;
170         }
171         for (i = md->start; i < md->start+md->homenr; i++)
172         {
173             for (w = 0; w < nwall; w++)
174             {
175                 /* The wall energy groups are always at the end of the list */
176                 ggid = gid[i]*ngid + ngid - nwall + w;
177                 at   = type[i];
178                 /* nbfp now includes the 6.0/12.0 derivative prefactors */
179                 Cd = nbfp[ntw[w]+2*at]/6.0;
180                 Cr = nbfp[ntw[w]+2*at+1]/12.0;
181                 if (!((Cd == 0 && Cr == 0) || (egp_flags[ggid] & EGP_EXCL)))
182                 {
183                     if (w == 0)
184                     {
185                         r = x[i][ZZ];
186                     }
187                     else
188                     {
189                         r = wall_z[1] - x[i][ZZ];
190                     }
191                     if (r < ir->wall_r_linpot)
192                     {
193                         mr = ir->wall_r_linpot - r;
194                         r  = ir->wall_r_linpot;
195                     }
196                     else
197                     {
198                         mr = 0;
199                     }
200                     switch (ir->wall_type)
201                     {
202                         case ewtTABLE:
203                             if (r < 0)
204                             {
205                                 wall_error(i, x, r);
206                             }
207                             tab      = &(fr->wall_tab[w][gid[i]]);
208                             tabscale = tab->scale;
209                             VFtab    = tab->data;
210
211                             rt    = r*tabscale;
212                             n0    = rt;
213                             if (n0 >= tab->n)
214                             {
215                                 /* Beyond the table range, set V and F to zero */
216                                 V     = 0;
217                                 F     = 0;
218                             }
219                             else
220                             {
221                                 eps   = rt - n0;
222                                 eps2  = eps*eps;
223                                 /* Dispersion */
224                                 nnn   = 8*n0;
225                                 Yt    = VFtab[nnn];
226                                 Ft    = VFtab[nnn+1];
227                                 Geps  = VFtab[nnn+2]*eps;
228                                 Heps2 = VFtab[nnn+3]*eps2;
229                                 Fp    = Ft + Geps + Heps2;
230                                 VV    = Yt + Fp*eps;
231                                 FF    = Fp + Geps + 2.0*Heps2;
232                                 Vd    = Cd*VV;
233                                 Fd    = Cd*FF;
234                                 /* Repulsion */
235                                 nnn   = nnn + 4;
236                                 Yt    = VFtab[nnn];
237                                 Ft    = VFtab[nnn+1];
238                                 Geps  = VFtab[nnn+2]*eps;
239                                 Heps2 = VFtab[nnn+3]*eps2;
240                                 Fp    = Ft + Geps + Heps2;
241                                 VV    = Yt + Fp*eps;
242                                 FF    = Fp + Geps + 2.0*Heps2;
243                                 Vr    = Cr*VV;
244                                 Fr    = Cr*FF;
245                                 V     = Vd + Vr;
246                                 F     = -lamfac*(Fd + Fr)*tabscale;
247                             }
248                             break;
249                         case ewt93:
250                             if (r <= 0)
251                             {
252                                 wall_error(i, x, r);
253                             }
254                             r1 = 1/r;
255                             r2 = r1*r1;
256                             r4 = r2*r2;
257                             Vd = fac_d[w]*Cd*r2*r1;
258                             Vr = fac_r[w]*Cr*r4*r4*r1;
259                             V  = Vr - Vd;
260                             F  = lamfac*(9*Vr - 3*Vd)*r1;
261                             break;
262                         case ewt104:
263                             if (r <= 0)
264                             {
265                                 wall_error(i, x, r);
266                             }
267                             r1 = 1/r;
268                             r2 = r1*r1;
269                             r4 = r2*r2;
270                             Vd = fac_d[w]*Cd*r4;
271                             Vr = fac_r[w]*Cr*r4*r4*r2;
272                             V  = Vr - Vd;
273                             F  = lamfac*(10*Vr - 4*Vd)*r1;
274                             break;
275                         case ewt126:
276                             if (r <= 0)
277                             {
278                                 wall_error(i, x, r);
279                             }
280                             r1 = 1/r;
281                             r2 = r1*r1;
282                             r4 = r2*r2;
283                             Vd = Cd*r4*r2;
284                             Vr = Cr*r4*r4*r4;
285                             V  = Vr - Vd;
286                             F  = lamfac*(12*Vr - 6*Vd)*r1;
287                             break;
288                         default:
289                             break;
290                     }
291                     if (mr > 0)
292                     {
293                         V += mr*F;
294                     }
295                     if (w == 1)
296                     {
297                         F = -F;
298                     }
299                     Vlj[ggid] += lamfac*V;
300                     Vtot      += V;
301                     f[i][ZZ]  += F;
302                     /* Because of the single sum virial calculation we need
303                      * to add  the full virial contribution of the walls.
304                      * Since the force only has a z-component, there is only
305                      * a contribution to the z component of the virial tensor.
306                      * We could also determine the virial contribution directly,
307                      * which would be cheaper here, but that would require extra
308                      * communication for f_novirsum for with virtual sites
309                      * in parallel.
310                      */
311                     xf_z[XX]  -= x[i][XX]*F;
312                     xf_z[YY]  -= x[i][YY]*F;
313                     xf_z[ZZ]  -= wall_z[w]*F;
314                 }
315             }
316         }
317         if (md->nPerturbed)
318         {
319             dvdlambda += (lam == 0 ? -1 : 1)*Vtot;
320         }
321
322         inc_nrnb(nrnb, eNR_WALLS, md->homenr);
323     }
324
325     for (i = 0; i < DIM; i++)
326     {
327         fr->vir_wall_z[i] = -0.5*xf_z[i];
328     }
329
330     return dvdlambda;
331 }