b435bcb3b0ac99d22960b313f6f6767625be1c28
[alexxy/gromacs.git] / src / gromacs / gmxana / gmx_mk_angndx.cpp
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) 2012,2013,2014,2015, 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 <cmath>
40
41 #include "gromacs/commandline/pargs.h"
42 #include "gromacs/fileio/trxio.h"
43 #include "gromacs/gmxana/gmx_ana.h"
44 #include "gromacs/legacyheaders/macros.h"
45 #include "gromacs/legacyheaders/typedefs.h"
46 #include "gromacs/utility/cstringutil.h"
47 #include "gromacs/utility/fatalerror.h"
48 #include "gromacs/utility/futil.h"
49 #include "gromacs/utility/gmxassert.h"
50 #include "gromacs/utility/smalloc.h"
51
52 static int calc_ntype(int nft, int *ft, t_idef *idef)
53 {
54     int  i, f, nf = 0;
55
56     for (i = 0; (i < idef->ntypes); i++)
57     {
58         for (f = 0; f < nft; f++)
59         {
60             if (idef->functype[i] == ft[f])
61             {
62                 nf++;
63             }
64         }
65     }
66
67     return nf;
68 }
69
70 static void fill_ft_ind(int nft, int *ft, t_idef *idef,
71                         int ft_ind[], char *grpnames[])
72 {
73     char buf[125];
74     int  i, f, ftype, ind = 0;
75
76     /* Loop over all the function types in the topology */
77     for (i = 0; (i < idef->ntypes); i++)
78     {
79         ft_ind[i] = -1;
80         /* Check all the selected function types */
81         for (f = 0; f < nft; f++)
82         {
83             ftype = ft[f];
84             if (idef->functype[i] == ftype)
85             {
86                 ft_ind[i] = ind;
87                 switch (ftype)
88                 {
89                     case F_ANGLES:
90                         sprintf(buf, "Theta=%.1f_%.2f", idef->iparams[i].harmonic.rA,
91                                 idef->iparams[i].harmonic.krA);
92                         break;
93                     case F_G96ANGLES:
94                         sprintf(buf, "Cos_th=%.1f_%.2f", idef->iparams[i].harmonic.rA,
95                                 idef->iparams[i].harmonic.krA);
96                         break;
97                     case F_UREY_BRADLEY:
98                         sprintf(buf, "UB_th=%.1f_%.2f2f", idef->iparams[i].u_b.thetaA,
99                                 idef->iparams[i].u_b.kthetaA);
100                         break;
101                     case F_QUARTIC_ANGLES:
102                         sprintf(buf, "Q_th=%.1f_%.2f_%.2f", idef->iparams[i].qangle.theta,
103                                 idef->iparams[i].qangle.c[0], idef->iparams[i].qangle.c[1]);
104                         break;
105                     case F_TABANGLES:
106                         sprintf(buf, "Table=%d_%.2f", idef->iparams[i].tab.table,
107                                 idef->iparams[i].tab.kA);
108                         break;
109                     case F_PDIHS:
110                         sprintf(buf, "Phi=%.1f_%d_%.2f", idef->iparams[i].pdihs.phiA,
111                                 idef->iparams[i].pdihs.mult, idef->iparams[i].pdihs.cpA);
112                         break;
113                     case F_IDIHS:
114                         sprintf(buf, "Xi=%.1f_%.2f", idef->iparams[i].harmonic.rA,
115                                 idef->iparams[i].harmonic.krA);
116                         break;
117                     case F_RBDIHS:
118                         sprintf(buf, "RB-A1=%.2f", idef->iparams[i].rbdihs.rbcA[1]);
119                         break;
120                     case  F_RESTRANGLES:
121                         sprintf(buf, "Theta=%.1f_%.2f", idef->iparams[i].harmonic.rA,
122                                 idef->iparams[i].harmonic.krA);
123                         break;
124                     case  F_RESTRDIHS:
125                         sprintf(buf, "Theta=%.1f_%.2f", idef->iparams[i].harmonic.rA,
126                                 idef->iparams[i].harmonic.krA);
127                         break;
128                     case  F_CBTDIHS:
129                         sprintf(buf, "CBT-A1=%.2f", idef->iparams[i].cbtdihs.cbtcA[1]);
130                         break;
131
132                     default:
133                         gmx_fatal(FARGS, "Unsupported function type '%s' selected",
134                                   interaction_function[ftype].longname);
135                 }
136                 grpnames[ind] = gmx_strdup(buf);
137                 ind++;
138             }
139         }
140     }
141 }
142
143 static void fill_ang(int nft, int *ft, int fac,
144                      int nr[], int *index[], int ft_ind[], t_topology *top,
145                      gmx_bool bNoH, real hq)
146 {
147     int         f, ftype, i, j, indg, nr_fac;
148     gmx_bool    bUse;
149     t_idef     *idef;
150     t_atom     *atom;
151     t_iatom    *ia;
152
153
154     idef = &top->idef;
155     atom = top->atoms.atom;
156
157     for (f = 0; f < nft; f++)
158     {
159         ftype = ft[f];
160         ia    = idef->il[ftype].iatoms;
161         for (i = 0; (i < idef->il[ftype].nr); )
162         {
163             indg = ft_ind[ia[0]];
164             if (indg == -1)
165             {
166                 gmx_incons("Routine fill_ang");
167             }
168             bUse = TRUE;
169             if (bNoH)
170             {
171                 for (j = 0; j < fac; j++)
172                 {
173                     if (atom[ia[1+j]].m < 1.5)
174                     {
175                         bUse = FALSE;
176                     }
177                 }
178             }
179             if (hq)
180             {
181                 for (j = 0; j < fac; j++)
182                 {
183                     if (atom[ia[1+j]].m < 1.5 && std::abs(atom[ia[1+j]].q) < hq)
184                     {
185                         bUse = FALSE;
186                     }
187                 }
188             }
189             if (bUse)
190             {
191                 if (nr[indg] % 1000 == 0)
192                 {
193                     srenew(index[indg], fac*(nr[indg]+1000));
194                 }
195                 nr_fac = fac*nr[indg];
196                 for (j = 0; (j < fac); j++)
197                 {
198                     index[indg][nr_fac+j] = ia[j+1];
199                 }
200                 nr[indg]++;
201             }
202             ia += interaction_function[ftype].nratoms+1;
203             i  += interaction_function[ftype].nratoms+1;
204         }
205     }
206 }
207
208 static int *select_ftype(const char *opt, int *nft, int *mult)
209 {
210     int *ft = NULL, ftype;
211
212     if (opt[0] == 'a')
213     {
214         *mult = 3;
215         for (ftype = 0; ftype < F_NRE; ftype++)
216         {
217             if ((interaction_function[ftype].flags & IF_ATYPE) ||
218                 ftype == F_TABANGLES)
219             {
220                 (*nft)++;
221                 srenew(ft, *nft);
222                 ft[*nft-1] = ftype;
223             }
224         }
225     }
226     else
227     {
228         *mult = 4;
229         *nft  = 1;
230         snew(ft, *nft);
231         switch (opt[0])
232         {
233             case 'd':
234                 ft[0] = F_PDIHS;
235                 break;
236             case 'i':
237                 ft[0] = F_IDIHS;
238                 break;
239             case 'r':
240                 ft[0] = F_RBDIHS;
241                 break;
242             default:
243                 break;
244         }
245     }
246
247     return ft;
248 }
249
250 int gmx_mk_angndx(int argc, char *argv[])
251 {
252     static const char *desc[] = {
253         "[THISMODULE] makes an index file for calculation of",
254         "angle distributions etc. It uses a run input file ([REF].tpx[ref]) for the",
255         "definitions of the angles, dihedrals etc."
256     };
257     static const char *opt[] = { NULL, "angle", "dihedral", "improper", "ryckaert-bellemans", NULL };
258     static gmx_bool    bH    = TRUE;
259     static real        hq    = -1;
260     t_pargs            pa[]  = {
261         { "-type", FALSE, etENUM, {opt},
262           "Type of angle" },
263         { "-hyd", FALSE, etBOOL, {&bH},
264           "Include angles with atoms with mass < 1.5" },
265         { "-hq", FALSE, etREAL, {&hq},
266           "Ignore angles with atoms with mass < 1.5 and magnitude of their charge less than this value" }
267     };
268
269     output_env_t       oenv;
270     FILE              *out;
271     t_topology        *top;
272     int                i, j, ntype;
273     int                nft = 0, *ft, mult = 0;
274     int              **index;
275     int               *ft_ind;
276     int               *nr;
277     char             **grpnames;
278     t_filenm           fnm[] = {
279         { efTPR, NULL, NULL, ffREAD  },
280         { efNDX, NULL, "angle", ffWRITE }
281     };
282 #define NFILE asize(fnm)
283
284     if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa,
285                            asize(desc), desc, 0, NULL, &oenv))
286     {
287         return 0;
288     }
289
290     GMX_RELEASE_ASSERT(opt[0] != 0, "Options inconsistency; opt[0] is NULL");
291
292     ft = select_ftype(opt[0], &nft, &mult);
293
294     top = read_top(ftp2fn(efTPR, NFILE, fnm), NULL);
295
296     ntype = calc_ntype(nft, ft, &(top->idef));
297     snew(grpnames, ntype);
298     snew(ft_ind, top->idef.ntypes);
299     fill_ft_ind(nft, ft, &top->idef, ft_ind, grpnames);
300
301     snew(nr, ntype);
302     snew(index, ntype);
303     fill_ang(nft, ft, mult, nr, index, ft_ind, top, !bH, hq);
304
305     out = ftp2FILE(efNDX, NFILE, fnm, "w");
306     for (i = 0; (i < ntype); i++)
307     {
308         if (nr[i] > 0)
309         {
310             fprintf(out, "[ %s ]\n", grpnames[i]);
311             for (j = 0; (j < nr[i]*mult); j++)
312             {
313                 fprintf(out, " %5d", index[i][j]+1);
314                 if ((j % 12) == 11)
315                 {
316                     fprintf(out, "\n");
317                 }
318             }
319             fprintf(out, "\n");
320         }
321     }
322     gmx_ffclose(out);
323
324     return 0;
325 }