Redefine the default boolean type to gmx_bool.
[alexxy/gromacs.git] / src / tools / gmx_bond.c
1 /*
2  * 
3  *                This source code is part of
4  * 
5  *                 G   R   O   M   A   C   S
6  * 
7  *          GROningen MAchine for Chemical Simulations
8  * 
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  * 
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * Green Red Orange Magenta Azure Cyan Skyblue
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38 #include <math.h>
39 #include <string.h>
40 #include "sysstuff.h"
41 #include "typedefs.h"
42 #include "smalloc.h"
43 #include "macros.h"
44 #include "vec.h"
45 #include "pbc.h"
46 #include "xvgr.h"
47 #include "copyrite.h"
48 #include "gmx_fatal.h"
49 #include "futil.h"
50 #include "statutil.h"
51 #include "index.h"
52 #include "gmx_statistics.h"
53 #include "tpxio.h"
54 #include "gmx_ana.h"
55
56
57 static void make_dist_leg(FILE *fp,int gnx,atom_id index[],t_atoms *atoms,
58                           const output_env_t oenv)
59 {
60   char **leg;
61   int  i;
62
63   snew(leg,gnx/2);
64   for(i=0; i<gnx; i+=2) {
65     snew(leg[i/2],256);
66     sprintf(leg[i/2],"%s %s%d - %s %s%d",
67             *(atoms->atomname[index[i]]),
68             *(atoms->resinfo[atoms->atom[index[i]].resind].name),
69             atoms->resinfo[atoms->atom[index[i]].resind].nr,
70             *(atoms->atomname[index[i+1]]),
71             *(atoms->resinfo[atoms->atom[index[i+1]].resind].name),
72             atoms->resinfo[atoms->atom[index[i+1]].resind].nr);
73   }
74   xvgr_legend(fp,gnx/2,(const char**)leg,oenv);
75   for(i=0; i<gnx/2; i++)
76     sfree(leg[i]);
77   sfree(leg);
78 }
79
80 static void do_bonds(FILE *log,const char *fn,const char *fbond,
81                      const char *fdist, int gnx,atom_id index[],
82                      real blen,real tol,gmx_bool bAver,
83                      t_topology *top,int ePBC,gmx_bool bAverDist,
84                      const output_env_t oenv)
85 {
86 #define MAXTAB 1000
87   FILE   *out,*outd=NULL;
88   int    *btab=NULL;
89   real   b0=0,b1,db=0;
90   real   bond,bav;
91   gmx_stats_t b_one=NULL,*b_all=NULL;
92   /*real   mean, mean2, sqrdev2, sigma2; 
93     int    counter;*/
94   rvec   *x;
95   rvec   dx;
96   t_trxstatus *status;
97   int    natoms;
98   matrix box;
99   real   t,fac;
100   int    bind,i,nframes,i0,i1;
101   t_pbc  pbc;
102   int    N;
103   real   aver,sigma,error;
104   
105   if (!bAver) {
106     snew(b_all,gnx/2);
107     for(i=0; (i<gnx/2); i++)
108       b_all[i] = gmx_stats_init();
109   }
110   else {
111     b_one = gmx_stats_init();
112     snew(btab,MAXTAB+1);
113   }
114   
115   natoms=read_first_x(oenv,&status,fn,&t,&x,box);
116   if (natoms == 0) 
117     gmx_fatal(FARGS,"No atoms in trajectory!");
118   
119   if (fdist) {
120     outd = xvgropen(fdist,bAverDist ? "Average distance" : "Distances",
121                     "Time (ps)","Distance (nm)",oenv);
122     if (!bAverDist) 
123       make_dist_leg(outd,gnx,index,&(top->atoms),oenv);
124   }
125   
126   nframes=0;
127   do {
128     set_pbc(&pbc,ePBC,box);
129     if (fdist)
130       fprintf(outd," %8.4f",t);
131     nframes++; /* count frames */
132     bav = 0.0;
133     for(i=0; (i<gnx); i+=2) {
134       pbc_dx(&pbc,x[index[i]],x[index[i+1]],dx);
135       bond   = norm(dx);
136       if (bAverDist)
137         bav += bond;
138       else if (fdist)
139         fprintf(outd," %.3f",bond);
140       if (bAver) {
141         gmx_stats_add_point(b_one,t,bond,0,0);
142         if (db == 0) {
143           if (blen == -1) {
144             b0 = 0;
145             b1 = 0.2;
146             db = (b1-b0)/MAXTAB;
147           }
148           else {
149             b0   = (1.0-tol)*blen;
150             b1   = (1.0+tol)*blen;
151             db   = (2.0*(b1-b0))/MAXTAB;
152           }
153         }
154         bind = (int)((bond-b0)/db+0.5);
155         if ((bind >= 0) && (bind <= MAXTAB))
156           btab[bind]++;
157         else {
158           /*
159             printf("bond: %4d-%4d bond=%10.5e, dx=(%10.5e,%10.5e,%10.5e)\n",
160             index[i],index[i+1],bond,dx[XX],dx[YY],dx[ZZ]);
161           */
162         }
163       }
164       else {
165         gmx_stats_add_point(b_all[i/2],t,bond,0,0);
166       }
167     }
168     if (bAverDist)
169       fprintf(outd," %.5f",bav*2.0/gnx);
170     if (fdist)
171       fprintf(outd,"\n");
172   } while (read_next_x(oenv,status,&t,natoms,x,box));
173   close_trj(status);
174
175   if (fdist)
176     ffclose(outd);
177   
178   /*
179     mean = mean / counter;
180     mean2 = mean2 / counter;
181     sqrdev2 = (mean2 - mean*mean);
182     sigma2 = sqrdev2*counter / (counter - 1);
183   */
184   /* For definitions see "Weet wat je meet" */
185   if (bAver) {
186     printf("\n");
187     gmx_stats_get_npoints(b_one,&N);
188     printf("Total number of samples               : %d\n",N);
189     gmx_stats_get_ase(b_one,&aver,&sigma,&error);
190     printf("Mean                                  : %g\n",aver);
191     printf("Standard deviation of the distribution: %g\n",sigma);
192     printf("Standard deviation of the mean        : %g\n",error);
193     gmx_stats_done(b_one);
194     sfree(b_one);
195             
196     out=xvgropen(fbond,"Bond Stretching Distribution",
197                  "Bond Length (nm)","",oenv);
198     
199     for(i0=0;      ((i0 < MAXTAB) && (btab[i0]==0)); i0++)
200       ;
201     i0=max(0,i0-1);
202     for(i1=MAXTAB; ((i1 > 0)      && (btab[i1]==0)); i1--)
203       ;
204     i1=min(MAXTAB,i1+1);
205     
206     if (i0 >= i1)
207       gmx_fatal(FARGS,"No distribution... (i0 = %d, i1 = %d)? ? ! ! ? !",i0,i1);
208     
209     fac=2.0/(nframes*gnx*db);
210     for(i=i0; (i<=i1); i++)
211       fprintf(out,"%8.5f  %8.5f\n",b0+i*db,btab[i]*fac);
212     ffclose(out);
213   }
214   else {
215     fprintf(log,"%5s  %5s  %8s  %8s\n","i","j","b_aver","sigma");
216     for(i=0; (i<gnx/2); i++) {
217       gmx_stats_get_ase(b_all[i],&aver,&sigma,NULL);
218       fprintf(log,"%5u  %5u  %8.5f  %8.5f\n",1+index[2*i],1+index[2*i+1],
219               aver,sigma);
220       gmx_stats_done(b_all[i]);
221       sfree(b_all[i]);
222     }
223     sfree(b_all);
224   }
225 }
226
227 int gmx_bond(int argc,char *argv[])
228 {
229   const char *desc[] = {
230     "g_bond makes a distribution of bond lengths. If all is well a",
231     "gaussian distribution should be made when using a harmonic potential.",
232     "Bonds are read from a single group in the index file in order i1-j1",
233     "i2-j2 through in-jn.[PAR]",
234     "[TT]-tol[tt] gives the half-width of the distribution as a fraction",
235     "of the bondlength ([TT]-blen[tt]). That means, for a bond of 0.2",
236     "a tol of 0.1 gives a distribution from 0.18 to 0.22.[PAR]",
237     "Option [TT]-d[tt] plots all the distances as a function of time.",
238     "This requires a structure file for the atom and residue names in",
239     "the output. If however the option [TT]-averdist[tt] is given (as well",
240     "or separately) the average bond length is plotted instead."
241   };
242   const char *bugs[] = {
243     "It should be possible to get bond information from the topology."
244   };
245   static real blen=-1.0,tol=0.1;
246   static gmx_bool bAver=TRUE,bAverDist=TRUE;
247   t_pargs pa[] = {
248     { "-blen", FALSE, etREAL, {&blen}, 
249       "Bond length. By default length of first bond" },
250     { "-tol",  FALSE, etREAL, {&tol}, 
251       "Half width of distribution as fraction of blen" },
252     { "-aver", FALSE, etBOOL, {&bAver},
253       "Average bond length distributions" },
254     { "-averdist", FALSE, etBOOL, {&bAverDist},
255       "Average distances (turns on -d)" }
256   };
257   FILE      *fp;
258   char      *grpname;
259   const char *fdist;
260   int       gnx;
261   atom_id   *index;
262   char      title[STRLEN];
263   t_topology top;
264   int       ePBC=-1;
265   rvec      *x;
266   matrix    box;
267   output_env_t oenv;
268
269   t_filenm fnm[] = {
270     { efTRX, "-f", NULL, ffREAD  },
271     { efNDX, NULL, NULL, ffREAD  },
272     { efTPS, NULL, NULL, ffOPTRD },
273     { efXVG, "-o", "bonds", ffWRITE },
274     { efLOG, NULL, "bonds", ffOPTWR },
275     { efXVG, "-d", "distance", ffOPTWR }
276   };
277 #define NFILE asize(fnm)
278
279   CopyRight(stderr,argv[0]);
280   parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE ,
281                     NFILE,fnm,asize(pa),pa,asize(desc),desc,asize(bugs),bugs,
282                     &oenv);
283   
284   if (bAverDist)
285     fdist = opt2fn("-d",NFILE,fnm);
286   else {
287     fdist = opt2fn_null("-d",NFILE,fnm);
288     if (fdist)
289       read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box,
290                     FALSE);
291   }
292   
293   rd_index(ftp2fn(efNDX,NFILE,fnm),1,&gnx,&index,&grpname);
294   if ( !even(gnx) )
295     fprintf(stderr,"WARNING: odd number of atoms (%d) in group!\n",gnx);
296   fprintf(stderr,"Will gather information on %d bonds\n",gnx/2);
297   
298   if (!bAver)
299     fp = ftp2FILE(efLOG,NFILE,fnm,"w");
300   else
301     fp = NULL;
302   
303   do_bonds(fp,ftp2fn(efTRX,NFILE,fnm),opt2fn("-o",NFILE,fnm),fdist,gnx,index,
304            blen,tol,bAver,&top,ePBC,bAverDist,oenv);
305   
306   do_view(oenv,opt2fn("-o",NFILE,fnm),"-nxy");
307   do_view(oenv,opt2fn_null("-d",NFILE,fnm),"-nxy");
308   
309   thanx(stderr);
310   
311   return 0;
312 }
313