3db4e4dce79b11daf6a3a3d01389a1ee118c878d
[alexxy/gromacs.git] / src / gromacs / mdlib / rf_util.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #include "gmxpre.h"
38
39 #include "config.h"
40
41 #include "gromacs/legacyheaders/typedefs.h"
42 #include "gromacs/legacyheaders/force.h"
43 #include "gromacs/legacyheaders/names.h"
44 #include "gromacs/legacyheaders/copyrite.h"
45
46 #include "gromacs/pbcutil/ishift.h"
47 #include "gromacs/pbcutil/mshift.h"
48 #include "gromacs/pbcutil/pbc.h"
49 #include "gromacs/math/units.h"
50 #include "gromacs/math/vec.h"
51
52 real RF_excl_correction(const t_forcerec *fr, t_graph *g,
53                         const t_mdatoms *mdatoms, const t_blocka *excl,
54                         rvec x[], rvec f[], rvec *fshift, const t_pbc *pbc,
55                         real lambda, real *dvdlambda)
56 {
57     /* Calculate the reaction-field energy correction for this node:
58      * epsfac q_i q_j (k_rf r_ij^2 - c_rf)
59      * and force correction for all excluded pairs, including self pairs.
60      */
61     int         top, i, j, j1, j2, k, ki;
62     double      q2sumA, q2sumB, ener;
63     const real *chargeA, *chargeB;
64     real        ek, ec, L1, qiA, qiB, qqA, qqB, qqL, v;
65     rvec        dx, df;
66     atom_id    *AA;
67     ivec        dt;
68     int         start = 0;
69     int         end   = mdatoms->homenr;
70     int         niat;
71     gmx_bool    bMolPBC = fr->bMolPBC;
72
73     if (fr->n_tpi)
74     {
75         /* For test particle insertion we only correct for the test molecule */
76         start = mdatoms->nr - fr->n_tpi;
77     }
78
79     ek      = fr->epsfac*fr->k_rf;
80     ec      = fr->epsfac*fr->c_rf;
81     chargeA = mdatoms->chargeA;
82     chargeB = mdatoms->chargeB;
83     AA      = excl->a;
84     ki      = CENTRAL;
85
86     if (fr->bDomDec)
87     {
88         niat = excl->nr;
89     }
90     else
91     {
92         niat = end;
93     }
94
95     q2sumA = 0;
96     q2sumB = 0;
97     ener   = 0;
98     if (mdatoms->nChargePerturbed == 0)
99     {
100         for (i = start; i < niat; i++)
101         {
102             qiA = chargeA[i];
103             if (i < end)
104             {
105                 q2sumA += qiA*qiA;
106             }
107             /* Do the exclusions */
108             j1  = excl->index[i];
109             j2  = excl->index[i+1];
110             for (j = j1; j < j2; j++)
111             {
112                 k = AA[j];
113                 if (k > i)
114                 {
115                     qqA = qiA*chargeA[k];
116                     if (qqA != 0)
117                     {
118                         if (g)
119                         {
120                             rvec_sub(x[i], x[k], dx);
121                             ivec_sub(SHIFT_IVEC(g, i), SHIFT_IVEC(g, k), dt);
122                             ki = IVEC2IS(dt);
123                         }
124                         else if (bMolPBC)
125                         {
126                             ki = pbc_dx_aiuc(pbc, x[i], x[k], dx);
127                         }
128                         else
129                         {
130                             rvec_sub(x[i], x[k], dx);
131                         }
132                         ener += qqA*(ek*norm2(dx) - ec);
133                         svmul(-2*qqA*ek, dx, df);
134                         rvec_inc(f[i], df);
135                         rvec_dec(f[k], df);
136                         rvec_inc(fshift[ki], df);
137                         rvec_dec(fshift[CENTRAL], df);
138                     }
139                 }
140             }
141         }
142         ener += -0.5*ec*q2sumA;
143     }
144     else
145     {
146         L1 = 1.0 - lambda;
147         for (i = start; i < niat; i++)
148         {
149             qiA = chargeA[i];
150             qiB = chargeB[i];
151             if (i < end)
152             {
153                 q2sumA += qiA*qiA;
154                 q2sumB += qiB*qiB;
155             }
156             /* Do the exclusions */
157             j1  = excl->index[i];
158             j2  = excl->index[i+1];
159             for (j = j1; j < j2; j++)
160             {
161                 k = AA[j];
162                 if (k > i)
163                 {
164                     qqA = qiA*chargeA[k];
165                     qqB = qiB*chargeB[k];
166                     if (qqA != 0 || qqB != 0)
167                     {
168                         qqL = L1*qqA + lambda*qqB;
169                         if (g)
170                         {
171                             rvec_sub(x[i], x[k], dx);
172                             ivec_sub(SHIFT_IVEC(g, i), SHIFT_IVEC(g, k), dt);
173                             ki = IVEC2IS(dt);
174                         }
175                         else if (bMolPBC)
176                         {
177                             ki = pbc_dx_aiuc(pbc, x[i], x[k], dx);
178                         }
179                         else
180                         {
181                             rvec_sub(x[i], x[k], dx);
182                         }
183                         v     = ek*norm2(dx) - ec;
184                         ener += qqL*v;
185                         svmul(-2*qqL*ek, dx, df);
186                         rvec_inc(f[i], df);
187                         rvec_dec(f[k], df);
188                         rvec_inc(fshift[ki], df);
189                         rvec_dec(fshift[CENTRAL], df);
190                         *dvdlambda += (qqB - qqA)*v;
191                     }
192                 }
193             }
194         }
195         ener       += -0.5*ec*(L1*q2sumA + lambda*q2sumB);
196         *dvdlambda += -0.5*ec*(q2sumB - q2sumA);
197     }
198
199     if (debug)
200     {
201         fprintf(debug, "RF exclusion energy: %g\n", ener);
202     }
203
204     return ener;
205 }
206
207 void calc_rffac(FILE *fplog, int eel, real eps_r, real eps_rf, real Rc, real Temp,
208                 real zsq, matrix box,
209                 real *kappa, real *krf, real *crf)
210 {
211     /* Compute constants for Generalized reaction field */
212     real   k1, k2, I, vol, rmin;
213
214     if (EEL_RF(eel))
215     {
216         vol     = det(box);
217         if (eel == eelGRF)
218         {
219             /* Consistency check */
220             if (Temp <= 0.0)
221             {
222                 gmx_fatal(FARGS, "Temperature is %f while using"
223                           " Generalized Reaction Field\n", Temp);
224             }
225             /* Ionic strength (only needed for eelGRF */
226             I       = 0.5*zsq/vol;
227             *kappa  = sqrt(2*I/(EPSILON0*eps_rf*BOLTZ*Temp));
228         }
229         else
230         {
231             I      = 0;
232             *kappa = 0;
233         }
234
235         /* eps == 0 signals infinite dielectric */
236         if (eps_rf == 0)
237         {
238             *krf = 1/(2*Rc*Rc*Rc);
239         }
240         else
241         {
242             k1   = 1 + *kappa*Rc;
243             k2   = eps_rf*sqr((real)(*kappa*Rc));
244
245             *krf = ((eps_rf - eps_r)*k1 + 0.5*k2)/((2*eps_rf + eps_r)*k1 + k2)/(Rc*Rc*Rc);
246         }
247         *crf   = 1/Rc + *krf*Rc*Rc;
248         rmin   = pow(*krf*2.0, -1.0/3.0);
249
250         if (fplog)
251         {
252             if (eel == eelGRF)
253             {
254                 please_cite(fplog, "Tironi95a");
255                 fprintf(fplog, "%s:\n"
256                         "epsRF = %10g, I   = %10g, volume = %10g, kappa  = %10g\n"
257                         "rc    = %10g, krf = %10g, crf    = %10g, epsfac = %10g\n",
258                         eel_names[eel], eps_rf, I, vol, *kappa, Rc, *krf, *crf,
259                         ONE_4PI_EPS0/eps_r);
260             }
261             else
262             {
263                 fprintf(fplog, "%s:\n"
264                         "epsRF = %g, rc = %g, krf = %g, crf = %g, epsfac = %g\n",
265                         eel_names[eel], eps_rf, Rc, *krf, *crf, ONE_4PI_EPS0/eps_r);
266             }
267             fprintf(fplog,
268                     "The electrostatics potential has its minimum at r = %g\n",
269                     rmin);
270         }
271     }
272 }
273
274 void init_generalized_rf(FILE *fplog,
275                          const gmx_mtop_t *mtop, const t_inputrec *ir,
276                          t_forcerec *fr)
277 {
278     int                  mb, i, j;
279     real                 q, zsq, nrdf, T;
280     const gmx_moltype_t *molt;
281     const t_block       *cgs;
282
283     if (ir->efep != efepNO && fplog)
284     {
285         fprintf(fplog, "\nWARNING: the generalized reaction field constants are determined from topology A only\n\n");
286     }
287     zsq = 0.0;
288     for (mb = 0; mb < mtop->nmolblock; mb++)
289     {
290         molt = &mtop->moltype[mtop->molblock[mb].type];
291         cgs  = &molt->cgs;
292         for (i = 0; (i < cgs->nr); i++)
293         {
294             q = 0;
295             for (j = cgs->index[i]; (j < cgs->index[i+1]); j++)
296             {
297                 q += molt->atoms.atom[j].q;
298             }
299             zsq += mtop->molblock[mb].nmol*q*q;
300         }
301         fr->zsquare = zsq;
302     }
303
304     T    = 0.0;
305     nrdf = 0.0;
306     for (i = 0; (i < ir->opts.ngtc); i++)
307     {
308         nrdf += ir->opts.nrdf[i];
309         T    += (ir->opts.nrdf[i] * ir->opts.ref_t[i]);
310     }
311     if (nrdf == 0)
312     {
313         gmx_fatal(FARGS, "No degrees of freedom!");
314     }
315     fr->temp   = T/nrdf;
316 }