Upped the version to 3.2.0
[gromacs.git] / src / tools / g_nmens.c
blob891c69c543571ff694598be0e9c3e7c7637fea6a
1 /*
2 * $Id$
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 3.2.0
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
33 * And Hey:
34 * Green Red Orange Magenta Azure Cyan Skyblue
36 #include <math.h>
37 #include <string.h>
38 #include "statutil.h"
39 #include "sysstuff.h"
40 #include "typedefs.h"
41 #include "smalloc.h"
42 #include "macros.h"
43 #include "fatal.h"
44 #include "vec.h"
45 #include "copyrite.h"
46 #include "futil.h"
47 #include "statutil.h"
48 #include "index.h"
49 #include "pdbio.h"
50 #include "tpxio.h"
51 #include "txtdump.h"
52 #include "physics.h"
53 #include "random.h"
54 #include "eigio.h"
56 int read_eigval(char *fn,int nmax,real eigval[])
58 FILE *fp;
59 char line[STRLEN];
60 int n,num;
61 double dbl;
62 bool bEndOfSet;
64 n=0;
65 fp = ffopen(fn,"r");
66 bEndOfSet = FALSE;
67 while (fgets(line,STRLEN-1,fp) && !bEndOfSet) {
68 bEndOfSet = (line[0] == '&');
69 if ((line[0] != '#') && (line[0] != '@') && !bEndOfSet) {
70 if ((sscanf(line,"%d %lf",&num,&dbl) != 2) || ((num < 1) || (num > nmax)))
71 fprintf(stderr,"Invalid line in %s: '%s'\n",fn,line);
72 else {
73 eigval[num-1] = dbl;
74 n++;
78 fclose(fp);
80 return n;
83 int gmx_nmens(int argc,char *argv[])
85 static char *desc[] = {
86 "[TT]g_nmens[tt] generates an ensemble around an average structure",
87 "in a subspace which is defined by a set of normal modes (eigenvectors).",
88 "The eigenvectors are assumed to be mass-weighted.",
89 "The position along each eigenvector is randomly taken from a Gaussian",
90 "distribution with variance kT/eigenvalue.[PAR]",
91 "By default the starting eigenvector is set to 7, since the first six",
92 "normal modes are the translational and rotational degrees of freedom."
94 static int nstruct=100,first=7,last=-1,seed=-1;
95 static real temp=300.0;
96 t_pargs pa[] = {
97 { "-temp", FALSE, etREAL, {&temp},
98 "Temperature in Kelvin" },
99 { "-seed", FALSE, etINT, {&seed},
100 "Random seed, -1 generates a seed from time and pid" },
101 { "-num", FALSE, etINT, {&nstruct},
102 "Number of structures to generate" },
103 { "-first", FALSE, etINT, {&first},
104 "First eigenvector to use (-1 is select)" },
105 { "-last", FALSE, etINT, {&last},
106 "Last eigenvector to use (-1 is till the last)" }
108 #define NPA asize(pa)
110 int out;
111 int status,trjout;
112 t_topology top;
113 t_atoms *atoms;
114 rvec *xtop,*xref,*xav,*xout1,*xout2;
115 bool bDMR,bDMA,bFit;
116 int nvec,*eignr=NULL;
117 rvec **eigvec=NULL;
118 matrix box;
119 real *eigval,totmass,*invsqrtm,t,disp;
120 int natoms,neigval;
121 char *grpname,*indexfile,title[STRLEN];
122 int i,j,d,s,v;
123 int nout,*iout,noutvec,*outvec;
124 atom_id *index;
125 real rfac,invfr,rhalf,jr;
126 unsigned long jran;
127 const unsigned long im = 0xffff;
128 const unsigned long ia = 1093;
129 const unsigned long ic = 18257;
131 t_filenm fnm[] = {
132 { efTRN, "-v", "eigenvec", ffREAD },
133 { efXVG, "-e", "eigenval", ffREAD },
134 { efTPS, NULL, NULL, ffREAD },
135 { efNDX, NULL, NULL, ffOPTRD },
136 { efTRX, "-o", "ensemble", ffWRITE }
138 #define NFILE asize(fnm)
140 CopyRight(stderr,argv[0]);
141 parse_common_args(&argc,argv,PCA_BE_NICE,
142 NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL);
144 indexfile=ftp2fn_null(efNDX,NFILE,fnm);
146 read_eigenvectors(opt2fn("-v",NFILE,fnm),&natoms,&bFit,
147 &xref,&bDMR,&xav,&bDMA,&nvec,&eignr,&eigvec);
149 read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&xtop,NULL,box,bDMA);
150 atoms=&top.atoms;
152 printf("\nSelect an index group of %d elements that corresponds to the eigenvectors\n",natoms);
153 get_index(atoms,indexfile,1,&i,&index,&grpname);
154 if (i!=natoms)
155 fatal_error(0,"you selected a group with %d elements instead of %d",
156 i,natoms);
157 printf("\n");
159 snew(eigval,DIM*natoms);
160 neigval=read_eigval(ftp2fn(efXVG,NFILE,fnm),DIM*natoms,eigval);
161 fprintf(stderr,"Read %d eigenvalues\n",neigval);
163 snew(invsqrtm,natoms);
164 if (bDMA) {
165 for(i=0; (i<natoms); i++)
166 invsqrtm[i] = invsqrt(atoms->atom[index[i]].m);
167 } else {
168 for(i=0; (i<natoms); i++)
169 invsqrtm[i]=1.0;
172 if (last==-1)
173 last=natoms*DIM;
174 if (first>-1) {
175 /* make an index from first to last */
176 nout=last-first+1;
177 snew(iout,nout);
178 for(i=0; i<nout; i++)
179 iout[i]=first-1+i;
180 } else {
181 printf("Select eigenvectors for output, end your selection with 0\n");
182 nout=-1;
183 iout=NULL;
184 do {
185 nout++;
186 srenew(iout,nout+1);
187 scanf("%d",&iout[nout]);
188 iout[nout]--;
189 } while (iout[nout]>=0);
190 printf("\n");
192 /* make an index of the eigenvectors which are present */
193 snew(outvec,nout);
194 noutvec=0;
195 for(i=0; i<nout; i++) {
196 j=0;
197 while ((j<nvec) && (eignr[j]!=iout[i]))
198 j++;
199 if ((j<nvec) && (eignr[j]==iout[i])) {
200 outvec[noutvec] = j;
201 iout[noutvec] = iout[i];
202 noutvec++;
205 fprintf(stderr,"%d eigenvectors selected for output\n",noutvec);
207 if (seed == -1)
208 seed = make_seed();
209 fprintf(stderr,"Using seed %d and a temperature of %g K\n",seed,temp);
211 snew(xout1,natoms);
212 snew(xout2,atoms->nr);
213 out=open_trx(ftp2fn(efTRX,NFILE,fnm),"w");
214 jran = (unsigned long)((real)im*rando(&seed));
215 for(s=0; s<nstruct; s++) {
216 for(i=0; i<natoms; i++)
217 copy_rvec(xav[i],xout1[i]);
218 for(j=0; j<noutvec; j++) {
219 v = outvec[j];
220 /* (r-0.5) n times: var_n = n * var_1 = n/12
221 n=4: var_n = 1/3, so multiply with 3 */
223 rfac = sqrt(3.0 * BOLTZ*temp/eigval[iout[j]]);
224 rhalf = 2.0*rfac;
225 rfac = rfac/(real)im;
227 jran = (jran*ia+ic) & im;
228 jr = (real)jran;
229 jran = (jran*ia+ic) & im;
230 jr += (real)jran;
231 jran = (jran*ia+ic) & im;
232 jr += (real)jran;
233 jran = (jran*ia+ic) & im;
234 jr += (real)jran;
235 disp = rfac * jr - rhalf;
237 for(i=0; i<natoms; i++)
238 for(d=0; d<DIM; d++)
239 xout1[i][d] += disp*eigvec[v][i][d]*invsqrtm[i];
241 for(i=0; i<natoms; i++)
242 copy_rvec(xout1[i],xout2[index[i]]);
243 t = s+1;
244 write_trx(out,natoms,index,atoms,0,t,box,xout2,NULL);
245 fprintf(stderr,"\rGenerated %d structures",s+1);
247 fprintf(stderr,"\n");
248 close_trx(out);
250 return 0;