edd6d73137e2597bb7d38bac39c6ec4a14f5f489
[alexxy/gromacs.git] / src / gromacs / gmxana / nrama.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 <math.h>
42 #include <stdlib.h>
43
44 #include "nrama.h"
45
46 #include "gromacs/bonded/bonded.h"
47 #include "gromacs/utility/futil.h"
48 #include "gromacs/utility/fatalerror.h"
49 #include "gromacs/utility/smalloc.h"
50 #include "gromacs/pbcutil/rmpbc.h"
51
52 static const char *pp_pat[] = { "C", "N", "CA", "C", "N" };
53 #define NPP (sizeof(pp_pat)/sizeof(pp_pat[0]))
54
55 static int d_comp(const void *a, const void *b)
56 {
57     t_dih *da, *db;
58
59     da = (t_dih *)a;
60     db = (t_dih *)b;
61
62     if (da->ai[1] < db->ai[1])
63     {
64         return -1;
65     }
66     else if (da->ai[1] == db->ai[1])
67     {
68         return (da->ai[2] - db->ai[2]);
69     }
70     else
71     {
72         return 1;
73     }
74 }
75
76
77 static void calc_dihs(t_xrama *xr)
78 {
79     int          i, t1, t2, t3;
80     rvec         r_ij, r_kj, r_kl, m, n;
81     real         sign;
82     t_dih       *dd;
83     gmx_rmpbc_t  gpbc = NULL;
84
85     gpbc = gmx_rmpbc_init(xr->idef, xr->ePBC, xr->natoms);
86     gmx_rmpbc(gpbc, xr->natoms, xr->box, xr->x);
87     gmx_rmpbc_done(gpbc);
88
89     for (i = 0; (i < xr->ndih); i++)
90     {
91         dd      = &(xr->dih[i]);
92         dd->ang = dih_angle(xr->x[dd->ai[0]], xr->x[dd->ai[1]],
93                             xr->x[dd->ai[2]], xr->x[dd->ai[3]],
94                             NULL,
95                             r_ij, r_kj, r_kl, m, n, &sign, &t1, &t2, &t3);
96     }
97 }
98
99 gmx_bool new_data(t_xrama *xr)
100 {
101     if (!read_next_x(xr->oenv, xr->traj, &xr->t, xr->x, xr->box))
102     {
103         return FALSE;
104     }
105
106     calc_dihs(xr);
107
108     return TRUE;
109 }
110
111 static int find_atom(const char *find, char ***names, int start, int nr)
112 {
113     int i;
114
115     for (i = start; (i < nr); i++)
116     {
117         if (strcmp(find, *names[i]) == 0)
118         {
119             return i;
120         }
121     }
122     return -1;
123 }
124
125 static void add_xr(t_xrama *xr, int ff[5], t_atoms *atoms)
126 {
127     char buf[12];
128     int  i;
129
130     srenew(xr->dih, xr->ndih+2);
131     for (i = 0; (i < 4); i++)
132     {
133         xr->dih[xr->ndih].ai[i] = ff[i];
134     }
135     for (i = 0; (i < 4); i++)
136     {
137         xr->dih[xr->ndih+1].ai[i] = ff[i+1];
138     }
139     xr->ndih += 2;
140
141     srenew(xr->pp, xr->npp+1);
142     xr->pp[xr->npp].iphi  = xr->ndih-2;
143     xr->pp[xr->npp].ipsi  = xr->ndih-1;
144     xr->pp[xr->npp].bShow = FALSE;
145     sprintf(buf, "%s-%d", *atoms->resinfo[atoms->atom[ff[1]].resind].name,
146             atoms->resinfo[atoms->atom[ff[1]].resind].nr);
147     xr->pp[xr->npp].label = gmx_strdup(buf);
148     xr->npp++;
149 }
150
151 static void get_dih(t_xrama *xr, t_atoms *atoms)
152 {
153     int    found, ff[NPP];
154     int    i;
155     size_t j;
156
157     for (i = 0; (i < atoms->nr); )
158     {
159         found = i;
160         for (j = 0; (j < NPP); j++)
161         {
162             if ((ff[j] = find_atom(pp_pat[j], atoms->atomname, found, atoms->nr)) == -1)
163             {
164                 break;
165             }
166             found = ff[j]+1;
167         }
168         if (j != NPP)
169         {
170             break;
171         }
172         add_xr(xr, ff, atoms);
173         i = ff[0]+1;
174     }
175     fprintf(stderr, "Found %d phi-psi combinations\n", xr->npp);
176 }
177
178 static int search_ff(int thisff[NPP], int ndih, int **ff)
179 {
180     int      j, k;
181     gmx_bool bFound = FALSE;
182
183     for (j = 0; (j < ndih); j++)
184     {
185         bFound = TRUE;
186         for (k = 1; (k <= 3); k++)
187         {
188             bFound = bFound && (thisff[k] == ff[j][k]);
189         }
190         if (bFound)
191         {
192             if (thisff[0] == -1)
193             {
194                 ff[j][4] = thisff[4];
195             }
196             else
197             {
198                 ff[j][0] = thisff[0];
199             }
200             break;
201         }
202     }
203     if (!bFound)
204     {
205         for (k = 0; (k < 5); k++)
206         {
207             ff[ndih][k] = thisff[k];
208         }
209         ndih++;
210     }
211     return ndih;
212 }
213
214 static void min_max(t_xrama *xr)
215 {
216     int ai, i, j;
217
218     xr->amin = xr->natoms;
219     xr->amax = 0;
220     for (i = 0; (i < xr->ndih); i++)
221     {
222         for (j = 0; (j < 4); j++)
223         {
224             ai = xr->dih[i].ai[j];
225             if (ai < xr->amin)
226             {
227                 xr->amin = ai;
228             }
229             else if (ai > xr->amax)
230             {
231                 xr->amax = ai;
232             }
233         }
234     }
235 }
236
237 static void get_dih_props(t_xrama *xr, t_idef *idef, int mult)
238 {
239     int      i, ft, ftype, nra;
240     t_iatom *ia;
241     t_dih   *dd, key;
242
243     ia = idef->il[F_PDIHS].iatoms;
244     for (i = 0; (i < idef->il[F_PDIHS].nr); )
245     {
246         ft    = ia[0];
247         ftype = idef->functype[ft];
248         nra   = interaction_function[ftype].nratoms;
249
250         if (ftype != F_PDIHS)
251         {
252             gmx_incons("ftype is not a dihedral");
253         }
254
255         key.ai[1] = ia[2];
256         key.ai[2] = ia[3];
257         if ((dd = (t_dih *)bsearch(&key, xr->dih, xr->ndih, (size_t)sizeof(key), d_comp))
258             != NULL)
259         {
260             dd->mult = idef->iparams[ft].pdihs.mult;
261             dd->phi0 = idef->iparams[ft].pdihs.phiA;
262         }
263
264         i  += nra+1;
265         ia += nra+1;
266     }
267     /* Fill in defaults for values not in the topology */
268     for (i = 0; (i < xr->ndih); i++)
269     {
270         if (xr->dih[i].mult == 0)
271         {
272             fprintf(stderr,
273                     "Dihedral around %d,%d not found in topology. Using mult=%d\n",
274                     xr->dih[i].ai[1], xr->dih[i].ai[2], mult);
275             xr->dih[i].mult = mult;
276             xr->dih[i].phi0 = 180;
277         }
278     }
279 }
280
281
282
283 t_topology *init_rama(const output_env_t oenv, const char *infile,
284                       const char *topfile, t_xrama *xr, int mult)
285 {
286     t_topology *top;
287     int         ePBC;
288     real        t;
289
290     top = read_top(topfile, &xr->ePBC);
291
292     /*get_dih2(xr,top->idef.functype,&(top->idef.bondeds),&(top->atoms));*/
293     get_dih(xr, &(top->atoms));
294     get_dih_props(xr, &(top->idef), mult);
295     xr->natoms = read_first_x(oenv, &xr->traj, infile, &t, &(xr->x), xr->box);
296     xr->idef   = &(top->idef);
297     xr->oenv   = oenv;
298
299     min_max(xr);
300     calc_dihs(xr);
301
302     return top;
303 }