d8348cf1b3a77f787a7c5b299156f13cd539c99b
[alexxy/gromacs.git] / src / tools / gmx_rotacf.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
39 #include <math.h>
40 #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 "index.h"
49 #include "macros.h"
50 #include "gmx_fatal.h"
51 #include "xvgr.h"
52 #include "gstat.h"
53 #include "vec.h"
54 #include "gmx_ana.h"
55
56
57 int gmx_rotacf(int argc,char *argv[])
58 {
59   const char *desc[] = {
60     "[TT]g_rotacf[tt] calculates the rotational correlation function",
61     "for molecules. Atom triplets (i,j,k) must be given in the index",
62     "file, defining two vectors ij and jk. The rotational ACF",
63     "is calculated as the autocorrelation function of the vector",
64     "n = ij x jk, i.e. the cross product of the two vectors.",
65     "Since three atoms span a plane, the order of the three atoms",
66     "does not matter. Optionally, by invoking the [TT]-d[tt] switch, you can",
67     "calculate the rotational correlation function for linear molecules",
68     "by specifying atom pairs (i,j) in the index file.",
69     "[PAR]",
70     "EXAMPLES[PAR]",
71     "[TT]g_rotacf -P 1 -nparm 2 -fft -n index -o rotacf-x-P1",
72     "-fa expfit-x-P1 -beginfit 2.5 -endfit 20.0[tt][PAR]",
73     "This will calculate the rotational correlation function using a first",
74     "order Legendre polynomial of the angle of a vector defined by the index",
75     "file. The correlation function will be fitted from 2.5 ps until 20.0 ps",
76     "to a two-parameter exponential."
77   };
78   static gmx_bool bVec    = FALSE,bAver=TRUE;
79
80   t_pargs pa[] = {
81     { "-d",   FALSE, etBOOL, {&bVec},
82       "Use index doublets (vectors) for correlation function instead of triplets (planes)" },
83     { "-aver",FALSE, etBOOL, {&bAver},
84       "Average over molecules" }
85   };
86
87   t_trxstatus *status;
88   int        isize;
89   atom_id    *index;
90   char       *grpname;
91   rvec       *x,*x_s;
92   matrix     box;
93   real       **c1;
94   rvec       xij,xjk,n;
95   int        i,m,teller,n_alloc,natoms,nvec,ai,aj,ak;
96   unsigned long mode;
97   real       t,t0,t1,dt;
98   gmx_rmpbc_t  gpbc=NULL;
99   t_topology *top;
100   int        ePBC;
101   t_filenm   fnm[] = {
102     { efTRX, "-f", NULL,  ffREAD  },
103     { efTPX, NULL, NULL,  ffREAD },
104     { efNDX, NULL, NULL,  ffREAD  },
105     { efXVG, "-o", "rotacf",  ffWRITE }
106   };
107 #define NFILE asize(fnm)
108   int     npargs;
109   t_pargs *ppa;
110
111   output_env_t oenv;
112   
113   CopyRight(stderr,argv[0]);
114   npargs = asize(pa);
115   ppa    = add_acf_pargs(&npargs,pa);
116   
117   parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
118                     NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
119   
120   rd_index(ftp2fn(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
121   
122   if (bVec) 
123     nvec = isize/2;
124   else
125     nvec = isize/3;
126   
127   if (((isize % 3) != 0) && !bVec)
128     gmx_fatal(FARGS,"number of index elements not multiple of 3, "
129                 "these can not be atom triplets\n");
130   if (((isize % 2) != 0) && bVec)
131     gmx_fatal(FARGS,"number of index elements not multiple of 2, "
132                 "these can not be atom doublets\n");
133   
134   top=read_top(ftp2fn(efTPX,NFILE,fnm),&ePBC);
135   
136   snew(c1,nvec);
137   for (i=0; (i<nvec); i++)
138     c1[i]=NULL;
139   n_alloc=0;
140
141   natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
142   snew(x_s,natoms);
143   
144   gpbc = gmx_rmpbc_init(&(top->idef),ePBC,natoms,box);
145
146   /* Start the loop over frames */
147   t1 = t0 = t;
148   teller  = 0;
149   do {
150     if (teller >= n_alloc) {
151       n_alloc+=100;
152       for (i=0; (i<nvec); i++)
153         srenew(c1[i],DIM*n_alloc);
154     }
155     t1 = t;
156     
157     /* Remove periodicity */
158     gmx_rmpbc_copy(gpbc,natoms,box,x,x_s);
159   
160     /* Compute crossproducts for all vectors, if triplets.
161      * else, just get the vectors in case of doublets.
162      */
163     if (bVec == FALSE) {
164       for (i=0; (i<nvec); i++) {
165         ai=index[3*i];
166         aj=index[3*i+1];
167         ak=index[3*i+2];
168         rvec_sub(x_s[ai],x_s[aj],xij);
169         rvec_sub(x_s[aj],x_s[ak],xjk);
170         cprod(xij,xjk,n);
171         for(m=0; (m<DIM); m++)
172           c1[i][DIM*teller+m]=n[m];
173       }
174     }
175     else {
176       for (i=0; (i<nvec); i++) {
177         ai=index[2*i];
178         aj=index[2*i+1];
179         rvec_sub(x_s[ai],x_s[aj],n);
180         for(m=0; (m<DIM); m++)
181           c1[i][DIM*teller+m]=n[m];
182       }
183     }
184     /* Increment loop counter */
185     teller++;
186   } while (read_next_x(oenv,status,&t,natoms,x,box));  
187   close_trj(status); 
188   fprintf(stderr,"\nDone with trajectory\n");
189   
190   gmx_rmpbc_done(gpbc);
191
192
193   /* Autocorrelation function */
194   if (teller < 2)
195     fprintf(stderr,"Not enough frames for correlation function\n");
196   else {
197     dt=(t1 - t0)/(teller-1);
198     
199     mode = eacVector;
200     
201     do_autocorr(ftp2fn(efXVG,NFILE,fnm),oenv,"Rotational Correlation Function",
202                 teller,nvec,c1,dt,mode,bAver);
203   }
204
205   do_view(oenv,ftp2fn(efXVG,NFILE,fnm),NULL);
206     
207   thanx(stderr);
208     
209   return 0;
210 }