00dbf09dcfa342420d3774b9cf9f392f1a39269f
[alexxy/gromacs.git] / src / gromacs / gmxlib / chargegroup.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 <math.h>
40 #include "gromacs/legacyheaders/typedefs.h"
41 #include "gromacs/math/vec.h"
42 #include "gromacs/pbcutil/pbc.h"
43 #include "gromacs/utility/smalloc.h"
44 #include "gromacs/utility/fatalerror.h"
45 #include "gromacs/legacyheaders/chargegroup.h"
46
47
48 void calc_chargegroup_radii(const gmx_mtop_t *mtop, rvec *x,
49                             real *rvdw1, real *rvdw2,
50                             real *rcoul1, real *rcoul2)
51 {
52     real            r2v1, r2v2, r2c1, r2c2, r2;
53     int             ntype, i, j, mb, m, cg, a_mol, a0, a1, a;
54     gmx_bool       *bLJ;
55     gmx_molblock_t *molb;
56     gmx_moltype_t  *molt;
57     t_block        *cgs;
58     t_atom         *atom;
59     rvec            cen;
60
61     r2v1 = 0;
62     r2v2 = 0;
63     r2c1 = 0;
64     r2c2 = 0;
65
66     ntype = mtop->ffparams.atnr;
67     snew(bLJ, ntype);
68     for (i = 0; i < ntype; i++)
69     {
70         bLJ[i] = FALSE;
71         for (j = 0; j < ntype; j++)
72         {
73             if (mtop->ffparams.iparams[i*ntype+j].lj.c6  != 0 ||
74                 mtop->ffparams.iparams[i*ntype+j].lj.c12 != 0)
75             {
76                 bLJ[i] = TRUE;
77             }
78         }
79     }
80
81     a_mol = 0;
82     for (mb = 0; mb < mtop->nmolblock; mb++)
83     {
84         molb = &mtop->molblock[mb];
85         molt = &mtop->moltype[molb->type];
86         cgs  = &molt->cgs;
87         atom = molt->atoms.atom;
88         for (m = 0; m < molb->nmol; m++)
89         {
90             for (cg = 0; cg < cgs->nr; cg++)
91             {
92                 a0 = cgs->index[cg];
93                 a1 = cgs->index[cg+1];
94                 if (a1 - a0 > 1)
95                 {
96                     clear_rvec(cen);
97                     for (a = a0; a < a1; a++)
98                     {
99                         rvec_inc(cen, x[a_mol+a]);
100                     }
101                     svmul(1.0/(a1-a0), cen, cen);
102                     for (a = a0; a < a1; a++)
103                     {
104                         r2 = distance2(cen, x[a_mol+a]);
105                         if (r2 > r2v2 && (bLJ[atom[a].type ] ||
106                                           bLJ[atom[a].typeB]))
107                         {
108                             if (r2 > r2v1)
109                             {
110                                 r2v2 = r2v1;
111                                 r2v1 = r2;
112                             }
113                             else
114                             {
115                                 r2v2 = r2;
116                             }
117                         }
118                         if (r2 > r2c2 &&
119                             (atom[a].q != 0 || atom[a].qB != 0))
120                         {
121                             if (r2 > r2c1)
122                             {
123                                 r2c2 = r2c1;
124                                 r2c1 = r2;
125                             }
126                             else
127                             {
128                                 r2c2 = r2;
129                             }
130                         }
131                     }
132                 }
133             }
134             a_mol += molb->natoms_mol;
135         }
136     }
137
138     sfree(bLJ);
139
140     *rvdw1  = sqrt(r2v1);
141     *rvdw2  = sqrt(r2v2);
142     *rcoul1 = sqrt(r2c1);
143     *rcoul2 = sqrt(r2c2);
144 }
145
146 void calc_cgcm(FILE gmx_unused *fplog, int cg0, int cg1, t_block *cgs,
147                rvec pos[], rvec cg_cm[])
148 {
149     int      icg, k, k0, k1, d;
150     rvec     cg;
151     real     nrcg, inv_ncg;
152     atom_id *cgindex;
153
154 #ifdef DEBUG
155     fprintf(fplog, "Calculating centre of geometry for charge groups %d to %d\n",
156             cg0, cg1);
157 #endif
158     cgindex = cgs->index;
159
160     /* Compute the center of geometry for all charge groups */
161     for (icg = cg0; (icg < cg1); icg++)
162     {
163         k0      = cgindex[icg];
164         k1      = cgindex[icg+1];
165         nrcg    = k1-k0;
166         if (nrcg == 1)
167         {
168             copy_rvec(pos[k0], cg_cm[icg]);
169         }
170         else
171         {
172             inv_ncg = 1.0/nrcg;
173
174             clear_rvec(cg);
175             for (k = k0; (k < k1); k++)
176             {
177                 for (d = 0; (d < DIM); d++)
178                 {
179                     cg[d] += pos[k][d];
180                 }
181             }
182             for (d = 0; (d < DIM); d++)
183             {
184                 cg_cm[icg][d] = inv_ncg*cg[d];
185             }
186         }
187     }
188 }
189
190 void put_charge_groups_in_box(FILE gmx_unused *fplog, int cg0, int cg1,
191                               int ePBC, matrix box, t_block *cgs,
192                               rvec pos[], rvec cg_cm[])
193
194 {
195     int      npbcdim, icg, k, k0, k1, d, e;
196     rvec     cg;
197     real     nrcg, inv_ncg;
198     atom_id *cgindex;
199     gmx_bool bTric;
200
201     if (ePBC == epbcNONE)
202     {
203         gmx_incons("Calling put_charge_groups_in_box for a system without PBC");
204     }
205
206 #ifdef DEBUG
207     fprintf(fplog, "Putting cgs %d to %d in box\n", cg0, cg1);
208 #endif
209     cgindex = cgs->index;
210
211     if (ePBC == epbcXY)
212     {
213         npbcdim = 2;
214     }
215     else
216     {
217         npbcdim = 3;
218     }
219
220     bTric = TRICLINIC(box);
221
222     for (icg = cg0; (icg < cg1); icg++)
223     {
224         /* First compute the center of geometry for this charge group */
225         k0      = cgindex[icg];
226         k1      = cgindex[icg+1];
227         nrcg    = k1-k0;
228
229         if (nrcg == 1)
230         {
231             copy_rvec(pos[k0], cg_cm[icg]);
232         }
233         else
234         {
235             inv_ncg = 1.0/nrcg;
236
237             clear_rvec(cg);
238             for (k = k0; (k < k1); k++)
239             {
240                 for (d = 0; d < DIM; d++)
241                 {
242                     cg[d] += pos[k][d];
243                 }
244             }
245             for (d = 0; d < DIM; d++)
246             {
247                 cg_cm[icg][d] = inv_ncg*cg[d];
248             }
249         }
250         /* Now check pbc for this cg */
251         if (bTric)
252         {
253             for (d = npbcdim-1; d >= 0; d--)
254             {
255                 while (cg_cm[icg][d] < 0)
256                 {
257                     for (e = d; e >= 0; e--)
258                     {
259                         cg_cm[icg][e] += box[d][e];
260                         for (k = k0; (k < k1); k++)
261                         {
262                             pos[k][e] += box[d][e];
263                         }
264                     }
265                 }
266                 while (cg_cm[icg][d] >= box[d][d])
267                 {
268                     for (e = d; e >= 0; e--)
269                     {
270                         cg_cm[icg][e] -= box[d][e];
271                         for (k = k0; (k < k1); k++)
272                         {
273                             pos[k][e] -= box[d][e];
274                         }
275                     }
276                 }
277             }
278         }
279         else
280         {
281             for (d = 0; d < npbcdim; d++)
282             {
283                 while (cg_cm[icg][d] < 0)
284                 {
285                     cg_cm[icg][d] += box[d][d];
286                     for (k = k0; (k < k1); k++)
287                     {
288                         pos[k][d] += box[d][d];
289                     }
290                 }
291                 while (cg_cm[icg][d] >= box[d][d])
292                 {
293                     cg_cm[icg][d] -= box[d][d];
294                     for (k = k0; (k < k1); k++)
295                     {
296                         pos[k][d] -= box[d][d];
297                     }
298                 }
299             }
300         }
301 #ifdef DEBUG_PBC
302         for (d = 0; (d < npbcdim); d++)
303         {
304             if ((cg_cm[icg][d] < 0) || (cg_cm[icg][d] >= box[d][d]))
305             {
306                 gmx_fatal(FARGS, "cg_cm[%d] = %15f  %15f  %15f\n"
307                           "box = %15f  %15f  %15f\n",
308                           icg, cg_cm[icg][XX], cg_cm[icg][YY], cg_cm[icg][ZZ],
309                           box[XX][XX], box[YY][YY], box[ZZ][ZZ]);
310             }
311         }
312 #endif
313     }
314 }