Enforced rotation: fixed torque calculation for FLEX potential when using mass-weighting
[gromacs/adressmacs.git] / src / tools / gmx_angle.c
blob6ad41553fb6846cbbe95325a6f913af3b5c8d728
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.
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.
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.
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.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * Green Red Orange Magenta Azure Cyan Skyblue
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38 #include <math.h>
39 #include <string.h>
41 #include "sysstuff.h"
42 #include "physics.h"
43 #include "typedefs.h"
44 #include "smalloc.h"
45 #include "futil.h"
46 #include "statutil.h"
47 #include "copyrite.h"
48 #include "vec.h"
49 #include "index.h"
50 #include "macros.h"
51 #include "gmx_fatal.h"
52 #include "xvgr.h"
53 #include "gstat.h"
54 #include "trnio.h"
55 #include "gmx_ana.h"
58 static void dump_dih_trn(int nframes,int nangles,real **dih,const char *fn,
59 real dt)
61 int i,j,k,l,m,na;
62 t_fileio *trn;
63 rvec *x;
64 matrix box = {{2,0,0},{0,2,0},{0,0,2}};
66 na = (nangles*2);
67 if ((na % 3) != 0)
68 na = 1+na/3;
69 else
70 na = na/3;
71 printf("There are %d dihedrals. Will fill %d atom positions with cos/sin\n",
72 nangles,na);
73 snew(x,na);
74 trn = open_trn(fn,"w");
75 for(i=0; (i<nframes); i++) {
76 k = l = 0;
77 for(j=0; (j<nangles); j++) {
78 for(m=0; (m<2); m++) {
79 x[k][l] = (m == 0) ? cos(dih[j][i]) : sin(dih[j][i]);
80 l++;
81 if (l == DIM) {
82 l = 0;
83 k++;
87 fwrite_trn(trn,i,(real)i*dt,0,box,na,x,NULL,NULL);
89 close_trn(trn);
90 sfree(x);
93 int gmx_g_angle(int argc,char *argv[])
95 static const char *desc[] = {
96 "g_angle computes the angle distribution for a number of angles",
97 "or dihedrals. This way you can check whether your simulation",
98 "is correct. With option -ov you can plot the average angle of",
99 "a group of angles as a function of time. With the -all option",
100 "the first graph is the average, the rest are the individual angles.[PAR]",
101 "With the -of option g_angle also calculates the fraction of trans",
102 "dihedrals (only for dihedrals) as function of time, but this is",
103 "probably only fun for a selected few.[PAR]",
104 "With option -oc a dihedral correlation function is calculated.[PAR]",
105 "It should be noted that the indexfile should contain",
106 "atom-triples for angles or atom-quadruplets for dihedrals.",
107 "If this is not the case, the program will crash.[PAR]",
108 "With option [TT]-or[tt] a trajectory file is dumped containing cos and",
109 "sin of selected dihedral angles which subsequently can be used as",
110 "input for a PCA analysis using [TT]g_covar[tt]."
112 static const char *opt[] = { NULL, "angle", "dihedral", "improper", "ryckaert-bellemans", NULL };
113 static gmx_bool bALL=FALSE,bChandler=FALSE,bAverCorr=FALSE,bPBC=TRUE;
114 static real binwidth=1;
115 t_pargs pa[] = {
116 { "-type", FALSE, etENUM, {opt},
117 "Type of angle to analyse" },
118 { "-all", FALSE, etBOOL, {&bALL},
119 "Plot all angles separately in the averages file, in the order of appearance in the index file." },
120 { "-binwidth", FALSE, etREAL, {&binwidth},
121 "binwidth (degrees) for calculating the distribution" },
122 { "-periodic", FALSE, etBOOL, {&bPBC},
123 "Print dihedral angles modulo 360 degrees" },
124 { "-chandler", FALSE, etBOOL, {&bChandler},
125 "Use Chandler correlation function (N[trans] = 1, N[gauche] = 0) rather than cosine correlation function. Trans is defined as phi < -60 || phi > 60." },
126 { "-avercorr", FALSE, etBOOL, {&bAverCorr},
127 "Average the correlation functions for the individual angles/dihedrals" }
129 static const char *bugs[] = {
130 "Counting transitions only works for dihedrals with multiplicity 3"
133 FILE *out;
134 real tmp,dt;
135 int status,isize;
136 atom_id *index;
137 char *grpname;
138 real maxang,Jc,S2,norm_fac,maxstat;
139 unsigned long mode;
140 int nframes,maxangstat,mult,*angstat;
141 int i,j,total,nangles,natoms,nat2,first,last,angind;
142 gmx_bool bAver,bRb,bPeriodic,
143 bFrac, /* calculate fraction too? */
144 bTrans, /* worry about transtions too? */
145 bCorr; /* correlation function ? */
146 real t,aa,aver,aver2,aversig,fraction; /* fraction trans dihedrals */
147 double tfrac=0;
148 char title[256];
149 real **dih=NULL; /* mega array with all dih. angles at all times*/
150 char buf[80];
151 real *time,*trans_frac,*aver_angle;
152 t_filenm fnm[] = {
153 { efTRX, "-f", NULL, ffREAD },
154 { efNDX, NULL, "angle", ffREAD },
155 { efXVG, "-od", "angdist", ffWRITE },
156 { efXVG, "-ov", "angaver", ffOPTWR },
157 { efXVG, "-of", "dihfrac", ffOPTWR },
158 { efXVG, "-ot", "dihtrans", ffOPTWR },
159 { efXVG, "-oh", "trhisto", ffOPTWR },
160 { efXVG, "-oc", "dihcorr", ffOPTWR },
161 { efTRR, "-or", NULL, ffOPTWR }
163 #define NFILE asize(fnm)
164 int npargs;
165 t_pargs *ppa;
166 output_env_t oenv;
168 CopyRight(stderr,argv[0]);
169 npargs = asize(pa);
170 ppa = add_acf_pargs(&npargs,pa);
171 parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
172 NFILE,fnm,npargs,ppa,asize(desc),desc,asize(bugs),bugs,
173 &oenv);
175 mult = 4;
176 maxang = 360.0;
177 bRb = FALSE;
178 switch(opt[0][0]) {
179 case 'a':
180 mult = 3;
181 maxang = 180.0;
182 break;
183 case 'd':
184 break;
185 case 'i':
186 break;
187 case 'r':
188 bRb = TRUE;
189 break;
192 if (opt2bSet("-or",NFILE,fnm)) {
193 if (mult != 4)
194 gmx_fatal(FARGS,"Can not combine angles with trn dump");
195 else
196 please_cite(stdout,"Mu2005a");
199 /* Calculate bin size */
200 maxangstat=(int)(maxang/binwidth+0.5);
201 binwidth=maxang/maxangstat;
203 rd_index(ftp2fn(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
204 nangles=isize/mult;
205 if ((isize % mult) != 0)
206 gmx_fatal(FARGS,"number of index elements not multiple of %d, "
207 "these can not be %s\n",
208 mult,(mult==3) ? "angle triplets" : "dihedral quadruplets");
211 /* Check whether specific analysis has to be performed */
212 bCorr=opt2bSet("-oc",NFILE,fnm);
213 bAver=opt2bSet("-ov",NFILE,fnm);
214 bTrans=opt2bSet("-ot",NFILE,fnm);
215 bFrac=opt2bSet("-of",NFILE,fnm);
217 if (bChandler && !bCorr)
218 bCorr=TRUE;
220 if (bFrac && !bRb) {
221 fprintf(stderr,"Warning:"
222 " calculating fractions as defined in this program\n"
223 "makes sense for Ryckaert Bellemans dihs. only. Ignoring -of\n\n");
224 bFrac = FALSE;
227 if ( (bTrans || bFrac || bCorr) && mult==3)
228 gmx_fatal(FARGS,"Can only do transition, fraction or correlation\n"
229 "on dihedrals. Select -d\n");
232 * We need to know the nr of frames so we can allocate memory for an array
233 * with all dihedral angles at all timesteps. Works for me.
235 if (bTrans || bCorr || bALL || opt2bSet("-or",NFILE,fnm))
236 snew(dih,nangles);
238 snew(angstat,maxangstat);
240 read_ang_dih(ftp2fn(efTRX,NFILE,fnm),(mult == 3),
241 bALL || bCorr || bTrans || opt2bSet("-or",NFILE,fnm),
242 bRb,bPBC,maxangstat,angstat,
243 &nframes,&time,isize,index,&trans_frac,&aver_angle,dih,
244 oenv);
246 dt=(time[nframes-1]-time[0])/(nframes-1);
248 if (bAver) {
249 sprintf(title,"Average Angle: %s",grpname);
250 out=xvgropen(opt2fn("-ov",NFILE,fnm),
251 title,"Time (ps)","Angle (degrees)",oenv);
252 for(i=0; (i<nframes); i++) {
253 fprintf(out,"%10.5f %8.3f",time[i],aver_angle[i]*RAD2DEG);
254 if (bALL) {
255 for(j=0; (j<nangles); j++)
256 if (bPBC) {
257 real dd = dih[j][i];
258 fprintf(out," %8.3f",atan2(sin(dd),cos(dd))*RAD2DEG);
260 else
261 fprintf(out," %8.3f",dih[j][i]*RAD2DEG);
263 fprintf(out,"\n");
265 ffclose(out);
267 if (opt2bSet("-or",NFILE,fnm))
268 dump_dih_trn(nframes,nangles,dih,opt2fn("-or",NFILE,fnm),dt);
270 if (bFrac) {
271 sprintf(title,"Trans fraction: %s",grpname);
272 out=xvgropen(opt2fn("-of",NFILE,fnm),
273 title,"Time (ps)","Fraction",oenv);
274 tfrac = 0.0;
275 for(i=0; (i<nframes); i++) {
276 fprintf(out,"%10.5f %10.3f\n",time[i],trans_frac[i]);
277 tfrac += trans_frac[i];
279 ffclose(out);
281 tfrac/=nframes;
282 fprintf(stderr,"Average trans fraction: %g\n",tfrac);
284 sfree(trans_frac);
286 if (bTrans)
287 ana_dih_trans(opt2fn("-ot",NFILE,fnm),opt2fn("-oh",NFILE,fnm),
288 dih,nframes,nangles,grpname,time[0],dt,bRb,oenv);
290 if (bCorr) {
291 /* Autocorrelation function */
292 if (nframes < 2)
293 fprintf(stderr,"Not enough frames for correlation function\n");
294 else {
296 if (bChandler) {
297 real dval,sixty=DEG2RAD*60;
298 gmx_bool bTest;
300 for(i=0; (i<nangles); i++)
301 for(j=0; (j<nframes); j++) {
302 dval = dih[i][j];
303 if (bRb)
304 bTest=(dval > -sixty) && (dval < sixty);
305 else
306 bTest=(dval < -sixty) || (dval > sixty);
307 if (bTest)
308 dih[i][j] = dval-tfrac;
309 else
310 dih[i][j] = -tfrac;
313 if (bChandler)
314 mode = eacNormal;
315 else
316 mode = eacCos;
317 do_autocorr(opt2fn("-oc",NFILE,fnm), oenv,
318 "Dihedral Autocorrelation Function",
319 nframes,nangles,dih,dt,mode,bAverCorr);
324 /* Determine the non-zero part of the distribution */
325 for(first=0; (first < maxangstat-1) && (angstat[first+1] == 0); first++)
327 for(last=maxangstat-1; (last > 0) && (angstat[last-1] == 0) ; last--)
330 aver=aver2=0;
331 for(i=0; (i<nframes); i++) {
332 aver += RAD2DEG*aver_angle[i];
333 aver2 += sqr(RAD2DEG*aver_angle[i]);
335 aver /= (real) nframes;
336 aver2 /= (real) nframes;
337 aversig = sqrt(aver2-sqr(aver));
338 printf("Found points in the range from %d to %d (max %d)\n",
339 first,last,maxangstat);
340 printf(" < angle > = %g\n",aver);
341 printf("< angle^2 > = %g\n",aver2);
342 printf("Std. Dev. = %g\n",aversig);
344 if (mult == 3)
345 sprintf(title,"Angle Distribution: %s",grpname);
346 else {
347 sprintf(title,"Dihedral Distribution: %s",grpname);
349 calc_distribution_props(maxangstat,angstat,-180.0,0,NULL,&S2);
350 fprintf(stderr,"Order parameter S^2 = %g\n",S2);
353 bPeriodic=(mult==4) && (first==0) && (last==maxangstat-1);
355 out=xvgropen(opt2fn("-od",NFILE,fnm),title,"Degrees","",oenv);
356 if (output_env_get_print_xvgr_codes(oenv))
357 fprintf(out,"@ subtitle \"average angle: %g\\So\\N\"\n",aver);
358 norm_fac=1.0/(nangles*nframes*binwidth);
359 if (bPeriodic) {
360 maxstat=0;
361 for(i=first; (i<=last); i++)
362 maxstat=max(maxstat,angstat[i]*norm_fac);
363 fprintf(out,"@with g0\n");
364 fprintf(out,"@ world xmin -180\n");
365 fprintf(out,"@ world xmax 180\n");
366 fprintf(out,"@ world ymin 0\n");
367 fprintf(out,"@ world ymax %g\n",maxstat*1.05);
368 fprintf(out,"@ xaxis tick major 60\n");
369 fprintf(out,"@ xaxis tick minor 30\n");
370 fprintf(out,"@ yaxis tick major 0.005\n");
371 fprintf(out,"@ yaxis tick minor 0.0025\n");
373 for(i=first; (i<=last); i++)
374 fprintf(out,"%10g %10f\n",i*binwidth+180.0-maxang,angstat[i]*norm_fac);
375 if ( bPeriodic )
376 /* print first bin again as last one */
377 fprintf(out,"%10g %10f\n",180.0,angstat[0]*norm_fac);
379 ffclose(out);
381 do_view(oenv,opt2fn("-od",NFILE,fnm),"-nxy");
382 if (bAver)
383 do_view(oenv,opt2fn("-ov",NFILE,fnm),"-nxy");
385 thanx(stderr);
387 return 0;