3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
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
33 * Green Red Orange Magenta Azure Cyan Skyblue
47 #include "gmx_fatal.h"
61 int gmx_nmtraj(int argc, char *argv[])
65 "[TT]g_nmtraj[tt] generates an virtual trajectory from an eigenvector, ",
66 "corresponding to a harmonic Cartesian oscillation around the average ",
67 "structure. The eigenvectors should normally be mass-weighted, but you can ",
68 "use non-weighted eigenvectors to generate orthogonal motions. ",
69 "The output frames are written as a trajectory file covering an entire period, and ",
70 "the first frame is the average structure. If you write the trajectory in (or convert to) ",
71 "PDB format you can view it directly in PyMol and also render a photorealistic movie. ",
72 "Motion amplitudes are calculated from the eigenvalues and a preset temperature, ",
73 "assuming equipartition of the energy over all modes. To make the motion clearly visible ",
74 "in PyMol you might want to amplify it by setting an unrealistically high temperature. ",
75 "However, be aware that both the linear Cartesian displacements and mass weighting will ",
76 "lead to serious structure deformation for high amplitudes - this is is simply a limitation ",
77 "of the Cartesian normal mode model. By default the selected eigenvector is set to 7, since ",
78 " the first six normal modes are the translational and rotational degrees of freedom."
81 static real refamplitude = 0.25;
82 static int nframes = 30;
83 static real temp = 300.0;
84 static const char *eignrvec = "7";
85 static const char *phasevec = "0.0";
89 { "-eignr", FALSE, etSTR, {&eignrvec}, "String of eigenvectors to use (first is 1)" },
90 { "-phases", FALSE, etSTR, {&phasevec}, "String of phases (default is 0.0)" },
91 { "-temp", FALSE, etREAL, {&temp}, "Temperature (K)" },
92 { "-amplitude", FALSE, etREAL, {&refamplitude}, "Amplitude for modes with eigenvalue<=0" },
93 { "-nframes", FALSE, etINT, {&nframes}, "Number of frames to generate" }
102 rvec *xtop, *xref, *xav, *xout;
103 int nvec, *eignr = NULL;
105 rvec **eigvec = NULL;
108 int i, j, k, kmode, d, s, v;
109 gmx_bool bDMR, bDMA, bFit;
122 real omega, Ekin, sum, m, vel;
135 { efTPS, NULL, NULL, ffREAD },
136 { efTRN, "-v", "eigenvec", ffREAD },
137 { efTRO, "-o", "nmtraj", ffWRITE }
140 #define NFILE asize(fnm)
142 parse_common_args(&argc, argv, PCA_BE_NICE,
143 NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv);
145 read_eigenvectors(opt2fn("-v", NFILE, fnm), &natoms, &bFit,
146 &xref, &bDMR, &xav, &bDMA, &nvec, &eignr, &eigvec, &eigval);
148 read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xtop, NULL, box, bDMA);
150 /* Find vectors and phases */
152 /* first find number of args in string */
157 dum = strtod(p, &pe);
162 snew(imodes, nmodes);
164 for (i = 0; i < nmodes; i++)
166 /* C indices start on 0 */
167 imodes[i] = strtol(p, &pe, 10)-1;
171 /* Now read phases */
176 dum = strtod(p, &pe);
180 if (nphases > nmodes)
182 gmx_fatal(FARGS, "More phases than eigenvector indices specified.\n");
185 snew(phases, nmodes);
188 for (i = 0; i < nphases; i++)
190 phases[i] = strtod(p, &pe);
194 if (nmodes > nphases)
196 printf("Warning: Setting phase of last %d modes to zero...\n", nmodes-nphases);
199 for (i = nphases; i < nmodes; i++)
206 if (atoms->nr != natoms)
208 gmx_fatal(FARGS, "Different number of atoms in topology and eigenvectors.\n");
212 for (i = 0; i < natoms; i++)
217 /* Find the eigenvalue/vector to match our select one */
218 snew(out_eigidx, nmodes);
219 for (i = 0; i < nmodes; i++)
224 for (i = 0; i < nvec; i++)
226 for (j = 0; j < nmodes; j++)
228 if (imodes[j] == eignr[i])
234 for (i = 0; i < nmodes; i++)
236 if (out_eigidx[i] == -1)
238 gmx_fatal(FARGS, "Could not find mode %d in eigenvector file.\n", imodes[i]);
243 snew(invsqrtm, natoms);
247 for (i = 0; (i < natoms); i++)
249 invsqrtm[i] = gmx_invsqrt(atoms->atom[i].m);
254 for (i = 0; (i < natoms); i++)
261 snew(amplitude, nmodes);
263 printf("mode phases: %g %g\n", phases[0], phases[1]);
265 for (i = 0; i < nmodes; i++)
267 kmode = out_eigidx[i];
268 this_eigvec = eigvec[kmode];
270 if ( (kmode >= 6) && (eigval[kmode] > 0))
272 /* Derive amplitude from temperature and eigenvalue if we can */
274 /* Convert eigenvalue to angular frequency, in units s^(-1) */
275 omega = sqrt(eigval[kmode]*1.0E21/(AVOGADRO*AMU));
276 /* Harmonic motion will be x=x0 + A*sin(omega*t)*eigenvec.
277 * The velocity is thus:
279 * v = A*omega*cos(omega*t)*eigenvec.
281 * And the average kinetic energy the integral of mass*v*v/2 over a
284 * (1/4)*mass*A*omega*eigenvec
286 * For t =2*pi*n, all energy will be kinetic, and v=A*omega*eigenvec.
287 * The kinetic energy will be sum(0.5*mass*v*v) if we temporarily set A to 1,
288 * and the average over a period half of this.
292 for (k = 0; k < natoms; k++)
294 m = atoms->atom[k].m;
295 for (d = 0; d < DIM; d++)
297 vel = omega*this_eigvec[k][d];
298 Ekin += 0.5*0.5*m*vel*vel;
302 /* Convert Ekin from amu*(nm/s)^2 to J, i.e., kg*(m/s)^2
303 * This will also be proportional to A^2
307 /* Set the amplitude so the energy is kT/2 */
308 amplitude[i] = sqrt(0.5*BOLTZMANN*temp/Ekin);
312 amplitude[i] = refamplitude;
316 out = open_trx(ftp2fn(efTRO, NFILE, fnm), "w");
318 /* Write a sine oscillation around the average structure,
319 * modulated by the eigenvector with selected amplitude.
322 for (i = 0; i < nframes; i++)
324 fraction = (real)i/(real)nframes;
325 for (j = 0; j < natoms; j++)
327 copy_rvec(xav[j], xout[j]);
330 for (k = 0; k < nmodes; k++)
332 kmode = out_eigidx[k];
333 this_eigvec = eigvec[kmode];
335 for (j = 0; j < natoms; j++)
337 for (d = 0; d < DIM; d++)
339 xout[j][d] += amplitude[k]*sin(2*M_PI*(fraction+phases[k]/360.0))*this_eigvec[j][d];
343 write_trx(out, natoms, dummy, atoms, i, (real)i/(real)nframes, box, xout, NULL, NULL);
346 fprintf(stderr, "\n");