2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012,2013, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
50 #include "gmx_fatal.h"
65 int gmx_nmtraj(int argc,char *argv[])
69 "[TT]g_nmtraj[tt] generates an virtual trajectory from an eigenvector, ",
70 "corresponding to a harmonic Cartesian oscillation around the average ",
71 "structure. The eigenvectors should normally be mass-weighted, but you can ",
72 "use non-weighted eigenvectors to generate orthogonal motions. ",
73 "The output frames are written as a trajectory file covering an entire period, and ",
74 "the first frame is the average structure. If you write the trajectory in (or convert to) ",
75 "PDB format you can view it directly in PyMol and also render a photorealistic movie. ",
76 "Motion amplitudes are calculated from the eigenvalues and a preset temperature, ",
77 "assuming equipartition of the energy over all modes. To make the motion clearly visible ",
78 "in PyMol you might want to amplify it by setting an unrealistically high temperature. ",
79 "However, be aware that both the linear Cartesian displacements and mass weighting will ",
80 "lead to serious structure deformation for high amplitudes - this is is simply a limitation ",
81 "of the Cartesian normal mode model. By default the selected eigenvector is set to 7, since ",
82 " the first six normal modes are the translational and rotational degrees of freedom."
85 static real refamplitude=0.25;
86 static int nframes=30;
87 static real temp=300.0;
88 static const char *eignrvec = "7";
89 static const char *phasevec = "0.0";
93 { "-eignr", FALSE, etSTR, {&eignrvec}, "String of eigenvectors to use (first is 1)" },
94 { "-phases", FALSE, etSTR, {&phasevec}, "String of phases (default is 0.0)" },
95 { "-temp", FALSE, etREAL, {&temp}, "Temperature (K)" },
96 { "-amplitude", FALSE, etREAL, {&refamplitude}, "Amplitude for modes with eigenvalue<=0" },
97 { "-nframes", FALSE, etINT, {&nframes}, "Number of frames to generate" }
100 #define NPA asize(pa)
106 rvec *xtop,*xref,*xav,*xout;
107 int nvec,*eignr=NULL;
112 int i,j,k,kmode,d,s,v;
113 gmx_bool bDMR,bDMA,bFit;
126 real omega,Ekin,sum,m,vel;
139 { efTPS, NULL, NULL, ffREAD },
140 { efTRN, "-v", "eigenvec", ffREAD },
141 { efTRO, "-o", "nmtraj", ffWRITE }
144 #define NFILE asize(fnm)
146 CopyRight(stderr,argv[0]);
147 parse_common_args(&argc,argv,PCA_BE_NICE,
148 NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL,&oenv);
150 read_eigenvectors(opt2fn("-v",NFILE,fnm),&natoms,&bFit,
151 &xref,&bDMR,&xav,&bDMA,&nvec,&eignr,&eigvec,&eigval);
153 read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,box,bDMA);
155 /* Find vectors and phases */
157 /* first find number of args in string */
169 for(i=0;i<nmodes;i++)
171 /* C indices start on 0 */
172 imodes[i]=strtol(p,&pe,10)-1;
176 /* Now read phases */
187 gmx_fatal(FARGS,"More phases than eigenvector indices specified.\n");
193 for(i=0;i<nphases;i++)
195 phases[i]=strtod(p,&pe);
201 printf("Warning: Setting phase of last %d modes to zero...\n",nmodes-nphases);
204 for(i=nphases;i<nmodes;i++)
211 if(atoms->nr != natoms)
213 gmx_fatal(FARGS,"Different number of atoms in topology and eigenvectors.\n");
217 for(i=0;i<natoms;i++)
220 /* Find the eigenvalue/vector to match our select one */
221 snew(out_eigidx,nmodes);
222 for(i=0;i<nmodes;i++)
227 for(j=0;j<nmodes;j++)
229 if(imodes[j]==eignr[i])
233 for(i=0;i<nmodes;i++)
234 if(out_eigidx[i]==-1)
235 gmx_fatal(FARGS,"Could not find mode %d in eigenvector file.\n",imodes[i]);
238 snew(invsqrtm,natoms);
242 for(i=0; (i<natoms); i++)
243 invsqrtm[i] = gmx_invsqrt(atoms->atom[i].m);
247 for(i=0; (i<natoms); i++)
252 snew(amplitude,nmodes);
254 printf("mode phases: %g %g\n",phases[0],phases[1]);
256 for(i=0;i<nmodes;i++)
258 kmode = out_eigidx[i];
259 this_eigvec=eigvec[kmode];
261 if( (kmode >= 6) && (eigval[kmode] > 0))
263 /* Derive amplitude from temperature and eigenvalue if we can */
265 /* Convert eigenvalue to angular frequency, in units s^(-1) */
266 omega = sqrt(eigval[kmode]*1.0E21/(AVOGADRO*AMU));
267 /* Harmonic motion will be x=x0 + A*sin(omega*t)*eigenvec.
268 * The velocity is thus:
270 * v = A*omega*cos(omega*t)*eigenvec.
272 * And the average kinetic energy the integral of mass*v*v/2 over a
275 * (1/4)*mass*A*omega*eigenvec
277 * For t =2*pi*n, all energy will be kinetic, and v=A*omega*eigenvec.
278 * The kinetic energy will be sum(0.5*mass*v*v) if we temporarily set A to 1,
279 * and the average over a period half of this.
283 for(k=0;k<natoms;k++)
285 m = atoms->atom[k].m;
288 vel = omega*this_eigvec[k][d];
289 Ekin += 0.5*0.5*m*vel*vel;
293 /* Convert Ekin from amu*(nm/s)^2 to J, i.e., kg*(m/s)^2
294 * This will also be proportional to A^2
298 /* Set the amplitude so the energy is kT/2 */
299 amplitude[i] = sqrt(0.5*BOLTZMANN*temp/Ekin);
303 amplitude[i] = refamplitude;
307 out=open_trx(ftp2fn(efTRO,NFILE,fnm),"w");
309 /* Write a sine oscillation around the average structure,
310 * modulated by the eigenvector with selected amplitude.
313 for(i=0;i<nframes;i++)
315 fraction = (real)i/(real)nframes;
316 for(j=0;j<natoms;j++)
318 copy_rvec(xav[j],xout[j]);
321 for(k=0;k<nmodes;k++)
324 this_eigvec=eigvec[kmode];
326 for(j=0;j<natoms;j++)
330 xout[j][d] += amplitude[k]*sin(2*M_PI*(fraction+phases[k]/360.0))*this_eigvec[j][d];
334 write_trx(out,natoms,dummy,atoms,i,(real)i/(real)nframes,box,xout,NULL,NULL);
337 fprintf(stderr,"\n");