SYCL: Avoid using no_init read accessor in rocFFT
[alexxy/gromacs.git] / src / gromacs / tools / 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,2016 by the GROMACS development team.
7  * Copyright (c) 2017,2018,2019,2020, by the GROMACS development team, led by
8  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9  * and including many others, as listed in the AUTHORS file in the
10  * top-level source directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 #include "gmxpre.h"
39
40 #include "mk_angndx.h"
41
42 #include <cmath>
43
44 #include "gromacs/commandline/pargs.h"
45 #include "gromacs/fileio/trxio.h"
46 #include "gromacs/topology/ifunc.h"
47 #include "gromacs/topology/topology.h"
48 #include "gromacs/utility/arraysize.h"
49 #include "gromacs/utility/cstringutil.h"
50 #include "gromacs/utility/fatalerror.h"
51 #include "gromacs/utility/futil.h"
52 #include "gromacs/utility/gmxassert.h"
53 #include "gromacs/utility/smalloc.h"
54
55 static int calc_ntype(int nft, const int* ft, const t_idef* idef)
56 {
57     int i, f, nf = 0;
58
59     for (i = 0; (i < idef->ntypes); i++)
60     {
61         for (f = 0; f < nft; f++)
62         {
63             if (idef->functype[i] == ft[f])
64             {
65                 nf++;
66             }
67         }
68     }
69
70     return nf;
71 }
72
73 static void fill_ft_ind(int nft, const int* ft, const t_idef* idef, int ft_ind[], char* grpnames[])
74 {
75     char buf[125];
76     int  i, f, ftype, ind = 0;
77
78     /* Loop over all the function types in the topology */
79     for (i = 0; (i < idef->ntypes); i++)
80     {
81         ft_ind[i] = -1;
82         /* Check all the selected function types */
83         for (f = 0; f < nft; f++)
84         {
85             ftype = ft[f];
86             if (idef->functype[i] == ftype)
87             {
88                 ft_ind[i] = ind;
89                 switch (ftype)
90                 {
91                     case F_ANGLES:
92                         sprintf(buf,
93                                 "Theta=%.1f_%.2f",
94                                 idef->iparams[i].harmonic.rA,
95                                 idef->iparams[i].harmonic.krA);
96                         break;
97                     case F_G96ANGLES:
98                         sprintf(buf,
99                                 "Cos_th=%.1f_%.2f",
100                                 idef->iparams[i].harmonic.rA,
101                                 idef->iparams[i].harmonic.krA);
102                         break;
103                     case F_UREY_BRADLEY:
104                         sprintf(buf,
105                                 "UB_th=%.1f_%.2f2f",
106                                 idef->iparams[i].u_b.thetaA,
107                                 idef->iparams[i].u_b.kthetaA);
108                         break;
109                     case F_QUARTIC_ANGLES:
110                         sprintf(buf,
111                                 "Q_th=%.1f_%.2f_%.2f",
112                                 idef->iparams[i].qangle.theta,
113                                 idef->iparams[i].qangle.c[0],
114                                 idef->iparams[i].qangle.c[1]);
115                         break;
116                     case F_TABANGLES:
117                         sprintf(buf,
118                                 "Table=%d_%.2f",
119                                 idef->iparams[i].tab.table,
120                                 idef->iparams[i].tab.kA);
121                         break;
122                     case F_PDIHS:
123                         sprintf(buf,
124                                 "Phi=%.1f_%d_%.2f",
125                                 idef->iparams[i].pdihs.phiA,
126                                 idef->iparams[i].pdihs.mult,
127                                 idef->iparams[i].pdihs.cpA);
128                         break;
129                     case F_IDIHS:
130                         sprintf(buf,
131                                 "Xi=%.1f_%.2f",
132                                 idef->iparams[i].harmonic.rA,
133                                 idef->iparams[i].harmonic.krA);
134                         break;
135                     case F_RBDIHS:
136                         sprintf(buf, "RB-A1=%.2f", idef->iparams[i].rbdihs.rbcA[1]);
137                         break;
138                     case F_RESTRANGLES:
139                         // Fall through intended
140                     case F_RESTRDIHS:
141                         sprintf(buf,
142                                 "Theta=%.1f_%.2f",
143                                 idef->iparams[i].harmonic.rA,
144                                 idef->iparams[i].harmonic.krA);
145                         break;
146                     case F_CBTDIHS:
147                         sprintf(buf, "CBT-A1=%.2f", idef->iparams[i].cbtdihs.cbtcA[1]);
148                         break;
149
150                     default:
151                         gmx_fatal(FARGS,
152                                   "Unsupported function type '%s' selected",
153                                   interaction_function[ftype].longname);
154                 }
155                 grpnames[ind] = gmx_strdup(buf);
156                 ind++;
157             }
158         }
159     }
160 }
161
162 static void fill_ang(int               nft,
163                      const int*        ft,
164                      int               fac,
165                      int               nr[],
166                      int*              index[],
167                      const int         ft_ind[],
168                      const t_topology* top,
169                      gmx_bool          bNoH,
170                      real              hq)
171 {
172     int           f, ftype, i, j, indg, nr_fac;
173     gmx_bool      bUse;
174     const t_idef* idef;
175     t_atom*       atom;
176     t_iatom*      ia;
177
178
179     idef = &top->idef;
180     atom = top->atoms.atom;
181
182     for (f = 0; f < nft; f++)
183     {
184         ftype = ft[f];
185         ia    = idef->il[ftype].iatoms;
186         for (i = 0; (i < idef->il[ftype].nr);)
187         {
188             indg = ft_ind[ia[0]];
189             if (indg == -1)
190             {
191                 gmx_incons("Routine fill_ang");
192             }
193             bUse = TRUE;
194             if (bNoH)
195             {
196                 for (j = 0; j < fac; j++)
197                 {
198                     if (atom[ia[1 + j]].m < 1.5)
199                     {
200                         bUse = FALSE;
201                     }
202                 }
203             }
204             if (hq != 0.0F)
205             {
206                 for (j = 0; j < fac; j++)
207                 {
208                     if (atom[ia[1 + j]].m < 1.5 && std::abs(atom[ia[1 + j]].q) < hq)
209                     {
210                         bUse = FALSE;
211                     }
212                 }
213             }
214             if (bUse)
215             {
216                 if (nr[indg] % 1000 == 0)
217                 {
218                     srenew(index[indg], fac * (nr[indg] + 1000));
219                 }
220                 nr_fac = fac * nr[indg];
221                 for (j = 0; (j < fac); j++)
222                 {
223                     index[indg][nr_fac + j] = ia[j + 1];
224                 }
225                 nr[indg]++;
226             }
227             ia += interaction_function[ftype].nratoms + 1;
228             i += interaction_function[ftype].nratoms + 1;
229         }
230     }
231 }
232
233 static int* select_ftype(const char* opt, int* nft, int* mult)
234 {
235     int *ft = nullptr, ftype;
236
237     if (opt[0] == 'a')
238     {
239         *mult = 3;
240         for (ftype = 0; ftype < F_NRE; ftype++)
241         {
242             if ((interaction_function[ftype].flags & IF_ATYPE) || ftype == F_TABANGLES)
243             {
244                 (*nft)++;
245                 srenew(ft, *nft);
246                 ft[*nft - 1] = ftype;
247             }
248         }
249     }
250     else
251     {
252         *mult = 4;
253         *nft  = 1;
254         snew(ft, *nft);
255         switch (opt[0])
256         {
257             case 'd': ft[0] = F_PDIHS; break;
258             case 'i': ft[0] = F_IDIHS; break;
259             case 'r': ft[0] = F_RBDIHS; break;
260             default: break;
261         }
262     }
263
264     return ft;
265 }
266
267 int gmx_mk_angndx(int argc, char* argv[])
268 {
269     static const char* desc[] = {
270         "[THISMODULE] makes an index file for calculation of",
271         "angle distributions etc. It uses a run input file ([REF].tpx[ref]) for the",
272         "definitions of the angles, dihedrals etc."
273     };
274     static const char* opt[] = { nullptr, "angle", "dihedral", "improper", "ryckaert-bellemans",
275                                  nullptr };
276     static gmx_bool    bH    = TRUE;
277     static real        hq    = -1;
278     t_pargs            pa[]  = { { "-type", FALSE, etENUM, { opt }, "Type of angle" },
279                      { "-hyd", FALSE, etBOOL, { &bH }, "Include angles with atoms with mass < 1.5" },
280                      { "-hq",
281                        FALSE,
282                        etREAL,
283                        { &hq },
284                        "Ignore angles with atoms with mass < 1.5 and magnitude of their charge "
285                        "less than this value" } };
286
287     gmx_output_env_t* oenv;
288     FILE*             out;
289     t_topology*       top;
290     int               i, j, ntype;
291     int               nft = 0, *ft, mult = 0;
292     int**             index;
293     int*              ft_ind;
294     int*              nr;
295     char**            grpnames;
296     t_filenm fnm[] = { { efTPR, nullptr, nullptr, ffREAD }, { efNDX, nullptr, "angle", ffWRITE } };
297 #define NFILE asize(fnm)
298
299     if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, nullptr, &oenv))
300     {
301         return 0;
302     }
303
304     GMX_RELEASE_ASSERT(opt[0] != nullptr, "Options inconsistency; opt[0] is NULL");
305
306     ft = select_ftype(opt[0], &nft, &mult);
307
308     top = read_top(ftp2fn(efTPR, NFILE, fnm), nullptr);
309
310     ntype = calc_ntype(nft, ft, &(top->idef));
311     snew(grpnames, ntype);
312     snew(ft_ind, top->idef.ntypes);
313     fill_ft_ind(nft, ft, &top->idef, ft_ind, grpnames);
314
315     snew(nr, ntype);
316     snew(index, ntype);
317     fill_ang(nft, ft, mult, nr, index, ft_ind, top, !bH, hq);
318
319     out = ftp2FILE(efNDX, NFILE, fnm, "w");
320     for (i = 0; (i < ntype); i++)
321     {
322         if (nr[i] > 0)
323         {
324             fprintf(out, "[ %s ]\n", grpnames[i]);
325             for (j = 0; (j < nr[i] * mult); j++)
326             {
327                 fprintf(out, " %5d", index[i][j] + 1);
328                 if ((j % 12) == 11)
329                 {
330                     fprintf(out, "\n");
331                 }
332             }
333             fprintf(out, "\n");
334         }
335     }
336     gmx_ffclose(out);
337
338     return 0;
339 }