Fixed make_edi.c
[gromacs/rigid-bodies.git] / src / tools / gmx_nmtraj.c
blob3d05d3709b263667c9bda6c7fbd4cf5974366d4f
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
39 #include <math.h>
40 #include <string.h>
42 #include "statutil.h"
43 #include "sysstuff.h"
44 #include "typedefs.h"
45 #include "smalloc.h"
46 #include "macros.h"
47 #include "gmx_fatal.h"
48 #include "vec.h"
49 #include "copyrite.h"
50 #include "futil.h"
51 #include "statutil.h"
52 #include "index.h"
53 #include "pdbio.h"
54 #include "tpxio.h"
55 #include "txtdump.h"
56 #include "physics.h"
57 #include "random.h"
58 #include "eigio.h"
59 #include "gmx_ana.h"
62 int gmx_nmtraj(int argc,char *argv[])
64 const char *desc[] =
66 "[TT]g_nmtraj[tt] generates an virtual trajectory from an eigenvector, ",
67 "corresponding to a harmonic cartesian oscillation around the average ",
68 "structure. The eigenvectors should normally be mass-weighted, but you can ",
69 "use non-weighted eigenvectors to generate orthogonal motions. ",
70 "The output frames are written as a trajectory file covering an entire period, and ",
71 "the first frame is the average structure. If you write the trajectory in (or convert to) ",
72 "PDB format you can view it directly in PyMol and also render a photorealistic movie. ",
73 "Motion amplitudes are calculated from the eigenvalues and a preset temperature, ",
74 "assuming equipartition of the energy over all modes. To make the motion clearly visible ",
75 "in PyMol you might want to amplify it by setting an unrealistic high temperature. ",
76 "However, be aware that both the linear cartesian displacements and mass weighting will ",
77 "lead to serious structure deformation for high amplitudes - this is is simply a limitation ",
78 "of the cartesian normal mode model. By default the selected eigenvector is set to 7, since ",
79 " the first six normal modes are the translational and rotational degrees of freedom."
82 static real refamplitude=0.25;
83 static int nframes=30;
84 static real temp=300.0;
85 static const char *eignrvec = "7";
86 static const char *phasevec = "0.0";
88 t_pargs pa[] =
90 { "-eignr", FALSE, etSTR, {&eignrvec}, "String of eigenvectors to use (first is 1)" },
91 { "-phases", FALSE, etSTR, {&phasevec}, "String of phases (default is 0.0)" },
92 { "-temp", FALSE, etREAL, {&temp}, "Temperature in Kelvin" },
93 { "-amplitude", FALSE, etREAL, {&refamplitude}, "Amplitude for modes with eigenvalue<=0" },
94 { "-nframes", FALSE, etINT, {&nframes}, "Number of frames to generate" }
97 #define NPA asize(pa)
99 int out;
100 t_topology top;
101 int ePBC;
102 t_atoms *atoms;
103 rvec *xtop,*xref,*xav,*xout;
104 int nvec,*eignr=NULL;
105 int *eigvalnr;
106 rvec **eigvec=NULL;
107 matrix box;
108 int natoms;
109 int i,j,k,kmode,d,s,v;
110 bool bDMR,bDMA,bFit;
111 char * indexfile;
113 char * grpname;
114 real * eigval;
115 int neigval;
116 int * dummy;
117 real * invsqrtm;
118 char title[STRLEN];
119 real fraction;
120 int *out_eigidx;
121 real *out_eigval;
122 rvec * this_eigvec;
123 real omega,Ekin,sum,m,vel;
124 bool found;
125 int nmodes,nphases;
126 int *imodes;
127 real *amplitude;
128 real *phases;
129 real dum;
130 const char *p;
131 char *pe;
132 output_env_t oenv;
134 t_filenm fnm[] =
136 { efTPS, NULL, NULL, ffREAD },
137 { efTRN, "-v", "eigenvec", ffREAD },
138 { efTRO, "-o", "nmtraj", ffWRITE }
141 #define NFILE asize(fnm)
143 CopyRight(stderr,argv[0]);
144 parse_common_args(&argc,argv,PCA_BE_NICE,
145 NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL,&oenv);
147 read_eigenvectors(opt2fn("-v",NFILE,fnm),&natoms,&bFit,
148 &xref,&bDMR,&xav,&bDMA,&nvec,&eignr,&eigvec,&eigval);
150 read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,box,bDMA);
152 /* Find vectors and phases */
154 /* first find number of args in string */
155 nmodes=0;
156 p=eignrvec;
157 while(*p!=0)
159 dum=strtod(p,&pe);
160 p=pe;
161 nmodes++;
164 snew(imodes,nmodes);
165 p=eignrvec;
166 for(i=0;i<nmodes;i++)
168 /* C indices start on 0 */
169 imodes[i]=strtol(p,&pe,10)-1;
170 p = pe;
173 /* Now read phases */
174 nphases=0;
175 p=phasevec;
176 while(*p!=0)
178 dum=strtod(p,&pe);
179 p=pe;
180 nphases++;
182 if(nphases>nmodes)
184 gmx_fatal(FARGS,"More phases than eigenvector indices specified.\n");
187 snew(phases,nmodes);
188 p=phasevec;
190 for(i=0;i<nphases;i++)
192 phases[i]=strtod(p,&pe);
193 p = pe;
196 if(nmodes>nphases)
198 printf("Warning: Setting phase of last %d modes to zero...\n",nmodes-nphases);
201 for(i=nphases;i<nmodes;i++)
203 phases[i]=0;
206 atoms=&top.atoms;
208 if(atoms->nr != natoms)
210 gmx_fatal(FARGS,"Different number of atoms in topology and eigenvectors.\n");
213 snew(dummy,natoms);
214 for(i=0;i<natoms;i++)
215 dummy[i]=i;
217 /* Find the eigenvalue/vector to match our select one */
218 snew(out_eigidx,nmodes);
219 for(i=0;i<nmodes;i++)
220 out_eigidx[i]=-1;
222 for(i=0;i<nvec;i++)
224 for(j=0;j<nmodes;j++)
226 if(imodes[j]==eignr[i])
227 out_eigidx[j]=i;
230 for(i=0;i<nmodes;i++)
231 if(out_eigidx[i]==-1)
232 gmx_fatal(FARGS,"Could not find mode %d in eigenvector file.\n",imodes[i]);
235 snew(invsqrtm,natoms);
237 if (bDMA)
239 for(i=0; (i<natoms); i++)
240 invsqrtm[i] = gmx_invsqrt(atoms->atom[i].m);
242 else
244 for(i=0; (i<natoms); i++)
245 invsqrtm[i]=1.0;
248 snew(xout,natoms);
249 snew(amplitude,nmodes);
251 printf("mode phases: %g %g\n",phases[0],phases[1]);
253 for(i=0;i<nmodes;i++)
255 kmode = out_eigidx[i];
256 this_eigvec=eigvec[kmode];
258 if( (kmode >= 6) && (eigval[kmode] > 0))
260 /* Derive amplitude from temperature and eigenvalue if we can */
262 /* Convert eigenvalue to angular frequency, in units s^(-1) */
263 omega = sqrt(eigval[kmode]*1.0E21/(AVOGADRO*AMU));
264 /* Harmonic motion will be x=x0 + A*sin(omega*t)*eigenvec.
265 * The velocity is thus:
267 * v = A*omega*cos(omega*t)*eigenvec.
269 * And the average kinetic energy the integral of mass*v*v/2 over a
270 * period:
272 * (1/4)*mass*A*omega*eigenvec
274 * For t =2*pi*n, all energy will be kinetic, and v=A*omega*eigenvec.
275 * The kinetic energy will be sum(0.5*mass*v*v) if we temporarily set A to 1,
276 * and the average over a period half of this.
279 Ekin = 0;
280 for(k=0;k<natoms;k++)
282 m = atoms->atom[k].m;
283 for(d=0;d<DIM;d++)
285 vel = omega*this_eigvec[k][d];
286 Ekin += 0.5*0.5*m*vel*vel;
290 /* Convert Ekin from amu*(nm/s)^2 to J, i.e., kg*(m/s)^2
291 * This will also be proportional to A^2
293 Ekin *= AMU*1E-18;
295 /* Set the amplitude so the energy is kT/2 */
296 amplitude[i] = sqrt(0.5*BOLTZMANN*temp/Ekin);
298 else
300 amplitude[i] = refamplitude;
304 out=open_trx(ftp2fn(efTRO,NFILE,fnm),"w");
306 /* Write a sine oscillation around the average structure,
307 * modulated by the eigenvector with selected amplitude.
310 for(i=0;i<nframes;i++)
312 fraction = (real)i/(real)nframes;
313 for(j=0;j<natoms;j++)
315 copy_rvec(xav[j],xout[j]);
318 for(k=0;k<nmodes;k++)
320 kmode=out_eigidx[k];
321 this_eigvec=eigvec[kmode];
323 for(j=0;j<natoms;j++)
325 for(d=0;d<DIM;d++)
327 xout[j][d] += amplitude[k]*sin(2*M_PI*(fraction+phases[k]/360.0))*this_eigvec[j][d];
331 write_trx(out,natoms,dummy,atoms,i,(real)i/(real)nframes,box,xout,NULL,NULL);
334 fprintf(stderr,"\n");
335 close_trx(out);
337 return 0;