3a109c1fa1cfe3d1484d784e6c2554c3fac7dff6
[alexxy/gromacs.git] / src / tools / make_edi.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  *
11  * The make_edi program was generously contributed by Oliver Lange, based
12  * on the code from g_anaeig. You can reach him as olange@gwdg.de.
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  * 
19  * If you want to redistribute modifications, please consider that
20  * scientific software is very special. Version control is crucial -
21  * bugs must be traceable. We will be happy to consider code for
22  * inclusion in the official distribution, but derived work must not
23  * be called official GROMACS. Details are found in the README & COPYING
24  * files - if they are missing, get the official version at www.gromacs.org.
25  *
26  * To help us fund GROMACS development, we humbly ask that you cite
27  * the papers on the package - you can find them in the top README file.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  *
31  * And Hey:
32  * Gromacs Runs One Microsecond At Cannonball Speeds
33  */
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include <math.h>
39 #include <stdlib.h>
40 #include <ctype.h>
41 #include <string.h>
42 #include "readinp.h"
43 #include "statutil.h"
44 #include "sysstuff.h"
45 #include "typedefs.h"
46 #include "smalloc.h"
47 #include "macros.h"
48 #include "gmx_fatal.h"
49 #include "vec.h"
50 #include "pbc.h"
51 #include "copyrite.h"
52 #include "futil.h"
53 #include "statutil.h"
54 #include "rdgroup.h"
55 #include "pdbio.h"
56 #include "confio.h"
57 #include "tpxio.h"
58 #include "matio.h"
59 #include "mshift.h"
60 #include "xvgr.h"
61 #include "do_fit.h"
62 #include "rmpbc.h"
63 #include "txtdump.h"
64 #include "eigio.h"
65 #include "index.h" 
66
67
68 typedef struct
69
70     real        deltaF0;
71     gmx_bool        bHarmonic;
72     real        tau;
73     real        deltaF;
74     real        kT; 
75     real        constEfl;
76     real        alpha2; 
77 } t_edflood;
78
79
80 /* This type is for the average, reference, target, and origin structure   */
81 typedef struct edix
82 {
83     int         nr;             /* number of atoms this structure contains */
84     int         *anrs;          /* atom index numbers                      */
85     rvec        *x;             /* positions                               */
86     real        *sqrtm;         /* sqrt of the masses used for mass-
87                                  * weighting of analysis                   */
88 } t_edix;
89
90
91 typedef struct edipar
92 {
93     int         nini;           /* total Nr of atoms                    */
94     gmx_bool        fitmas;         /* true if trans fit with cm            */
95     gmx_bool        pcamas;         /* true if mass-weighted PCA            */
96     int         presteps;       /* number of steps to run without any   
97                                  *    perturbations ... just monitoring */
98     int         outfrq;         /* freq (in steps) of writing to edo    */
99     int         maxedsteps;     /* max nr of steps per cycle            */
100     struct edix sref;           /* reference positions, to these fitting
101                                  * will be done                         */
102     struct edix sav;            /* average positions                    */
103     struct edix star;           /* target positions                     */
104     struct edix sori;           /* origin positions                     */
105     real        slope;          /* minimal slope in acceptance radexp   */
106     int         ned;            /* Nr of atoms in essdyn buffer         */
107     t_edflood   flood;          /* parameters especially for flooding   */
108 } t_edipar;
109
110
111
112 void make_t_edx(struct edix *edx, int natoms, rvec *pos, atom_id index[]) {
113   edx->nr=natoms;
114   edx->anrs=index;
115   edx->x=pos;
116 }
117
118 void write_t_edx(FILE *fp, struct edix edx, const char *comment) {
119  /*here we copy only the pointers into the t_edx struct
120   no data is copied and edx.box is ignored  */
121  int i;
122   fprintf(fp,"#%s \n %d \n",comment,edx.nr);
123   for (i=0;i<edx.nr;i++) {
124     fprintf(fp,"%d  %f  %f  %f\n",(edx.anrs)[i]+1,(edx.x)[i][XX],(edx.x)[i][YY],(edx.x)[i][ZZ]);
125   }
126 }
127
128 int sscan_list(int *list[], const char *str, const char *listname) {
129  /*this routine scans a string of the form 1,3-6,9 and returns the
130     selected numbers (in this case 1 3 4 5 6 9) in NULL-terminated array of integers.
131     memory for this list will be allocated  in this routine -- sscan_list expects *list to
132     be a NULL-Pointer
133
134     listname is a string used in the errormessage*/
135
136
137    int i,istep;
138    char c;
139    char *pos,*startpos,*step;
140    int n=strlen(str);
141
142    /*enums to define the different lexical stati */
143    enum { sBefore, sNumber, sMinus, sRange, sZero, sSmaller, sError, sSteppedRange };
144   
145    int status=sBefore; /*status of the deterministic automat to scan str   */
146    int number=0;
147    int end_number=0;
148     
149    char *start=NULL; /*holds the string of the number behind a ','*/
150    char *end=NULL; /*holds the string of the number behind a '-' */
151   
152    int nvecs=0; /* counts the number of vectors in the list*/
153
154    step=NULL;
155    snew(pos,n+4);
156    startpos=pos;
157    strcpy(pos,str);
158    pos[n]=',';  
159    pos[n+1]='1';
160    pos[n+2]='\0';
161
162    *list = NULL;
163      
164    while ((c=*pos)!=0) {
165      switch(status) {
166         /* expect a number */
167         case sBefore: if (isdigit(c)) {
168               start=pos;
169               status=sNumber;
170               break;
171            } else status=sError; break;
172
173         /* have read a number, expect ',' or '-' */
174         case sNumber: if (c==',') {
175              /*store number*/
176              srenew(*list,nvecs+1);
177              (*list)[nvecs++]=number=strtol(start,NULL,10);
178              status=sBefore;
179              if (number==0)
180                  status=sZero;
181               break;
182              } else if (c=='-') { status=sMinus; break; }
183              else if (isdigit(c)) break;
184              else status=sError; break;
185
186         /* have read a '-' -> expect a number */
187      case sMinus: 
188        if (isdigit(c)) {
189          end=pos;
190          status=sRange; break;
191        } else status=sError; break;
192        
193      case sSteppedRange:
194        if (isdigit(c)) {
195          if (step) {
196            status=sError; break; 
197          } else
198            step=pos;
199          status=sRange;
200          break;
201        } else status=sError; break;
202        
203         /* have read the number after a minus, expect ',' or ':' */
204         case sRange:
205             if (c==',') {
206                /*store numbers*/
207                end_number=strtol(end,NULL,10);
208                number=strtol(start,NULL,10);
209                status=sBefore;
210                if (number==0) {
211                   status=sZero; break;
212                }
213                if (end_number<=number) {
214                   status=sSmaller; break;
215                }
216                srenew(*list,nvecs+end_number-number+1);
217                if (step) {
218                  istep=strtol(step,NULL,10);
219                  step=NULL;
220                } else istep=1;
221                for (i=number;i<=end_number;i+=istep)
222                     (*list)[nvecs++]=i;
223                break;
224             } else if (c==':') {
225               status = sSteppedRange;
226               break;
227             } else if (isdigit(c)) break; else status=sError;  break;
228
229        /* format error occured */
230        case sError:
231        gmx_fatal(FARGS,"Error in the list of eigenvectors for %s at pos %d with char %c",listname,pos-startpos,*(pos-1)); 
232
233        /* logical error occured */
234        case sZero:
235                gmx_fatal(FARGS,"Error in the list of eigenvectors for %s at pos %d: eigenvector 0 is not valid",listname,pos-startpos);
236        case sSmaller:
237                gmx_fatal(FARGS,"Error in the list of eigenvectors for %s at pos %d: second index %d is not bigger than %d",listname,pos-startpos,end_number,number);
238
239      }
240    ++pos; /* read next character */
241    } /*scanner has finished */
242
243    /* append zero to list of eigenvectors */
244    srenew(*list,nvecs+1);
245    (*list)[nvecs]=0;
246    sfree(startpos);
247    return nvecs;
248 } /*sscan_list*/
249   
250 void write_eigvec(FILE* fp, int natoms, int eig_list[], rvec** eigvecs,int nvec, const char *grouptitle,real steps[]) {
251 /* eig_list is a zero-terminated list of indices into the eigvecs array.
252    eigvecs are coordinates of eigenvectors
253    grouptitle to write in the comment line
254    steps  -- array with stepsizes for evLINFIX, evLINACC and evRADACC
255 */
256
257   int n=0,i; rvec x;
258   real sum;
259   while (eig_list[n++]);  /*count selected eigenvecs*/
260   
261   fprintf(fp,"# NUMBER OF EIGENVECTORS + %s\n %d\n",grouptitle,n-1);
262   
263   /* write list of eigenvector indicess */
264   for(n=0;eig_list[n];n++) {
265     if (steps)
266       fprintf(fp,"%8d   %g\n",eig_list[n],steps[n]); 
267     else 
268       fprintf(fp,"%8d   %g\n",eig_list[n],1.0);
269   }
270   n=0;
271     
272   /* dump coordinates of the selected eigenvectors */
273   while (eig_list[n]) {
274     sum=0;
275     for (i=0; i<natoms; i++) {
276       if (eig_list[n]>nvec)
277         gmx_fatal(FARGS,"Selected eigenvector %d is higher than maximum number %d of available eigenvectors",eig_list[n],nvec);
278       copy_rvec(eigvecs[eig_list[n]-1][i],x);
279       sum+=norm2(x);
280       fprintf(fp,"%8.5f %8.5f %8.5f\n",x[XX],x[YY],x[ZZ]);      
281     }    
282     n++;
283   }
284 }
285
286
287 /*enum referring to the different lists of eigenvectors*/
288 enum { evLINFIX, evLINACC, evFLOOD, evRADFIX, evRADACC, evRADCON , evMON,  evEND };
289 #define oldMAGIC 666
290 #define MAGIC 669
291
292
293 void write_the_whole_thing(FILE* fp, t_edipar *edpars, rvec** eigvecs, 
294                            int nvec, int *eig_listen[], real* evStepList[]) 
295 {
296 /* write edi-file */
297
298     /*Header*/
299     fprintf(fp,"#MAGIC\n %d \n#NINI\n %d\n#FITMAS\n %d\n#ANALYSIS_MAS\n %d\n",
300         MAGIC,edpars->nini,edpars->fitmas,edpars->pcamas);
301     fprintf(fp,"#OUTFRQ\n %d\n#MAXLEN\n %d\n#SLOPECRIT\n %f\n",
302         edpars->outfrq,edpars->maxedsteps,edpars->slope);
303     fprintf(fp,"#PRESTEPS\n %d\n#DELTA_F0\n %f\n#INIT_DELTA_F\n %f\n#TAU\n %f\n#EFL_NULL\n %f\n#ALPHA2\n %f\n#KT\n %f\n#HARMONIC\n %d\n",
304         edpars->presteps,edpars->flood.deltaF0,edpars->flood.deltaF,edpars->flood.tau,edpars->flood.constEfl,edpars->flood.alpha2,edpars->flood.kT,edpars->flood.bHarmonic);
305     
306     /* Average and reference positions */
307     write_t_edx(fp,edpars->sref,"NREF, XREF");
308     write_t_edx(fp,edpars->sav,"NAV, XAV");
309
310     /*Eigenvectors */
311  
312     write_eigvec(fp, edpars->ned, eig_listen[evMON],eigvecs,nvec,"COMPONENTS GROUP 1",NULL);
313     write_eigvec(fp, edpars->ned, eig_listen[evLINFIX],eigvecs,nvec,"COMPONENTS GROUP 2",evStepList[evLINFIX]);
314     write_eigvec(fp, edpars->ned, eig_listen[evLINACC],eigvecs,nvec,"COMPONENTS GROUP 3",evStepList[evLINACC]);
315     write_eigvec(fp, edpars->ned, eig_listen[evRADFIX],eigvecs,nvec,"COMPONENTS GROUP 4",evStepList[evRADFIX]);
316     write_eigvec(fp, edpars->ned, eig_listen[evRADACC],eigvecs,nvec,"COMPONENTS GROUP 5",NULL);
317     write_eigvec(fp, edpars->ned, eig_listen[evRADCON],eigvecs,nvec,"COMPONENTS GROUP 6",NULL);
318     write_eigvec(fp, edpars->ned, eig_listen[evFLOOD],eigvecs,nvec,"COMPONENTS GROUP 7",evStepList[evFLOOD]);
319
320
321     /*Target and Origin positions */
322     write_t_edx(fp,edpars->star,"NTARGET, XTARGET");
323     write_t_edx(fp,edpars->sori,"NORIGIN, XORIGIN");
324
325
326 int read_conffile(const char *confin,char *title,rvec *x[]) 
327 {
328 /* read coordinates out of STX file  */
329   int natoms;
330   t_atoms  confat;
331   matrix box;
332   printf("read coordnumber from file %s\n",confin);
333   get_stx_coordnum(confin,&natoms);
334   printf("number of coordinates in file %d\n",natoms);
335 /*  if (natoms != ncoords)
336      gmx_fatal(FARGS,"number of coordinates in coordinate file (%s, %d)\n"
337            "             does not match topology (= %d)",
338            confin,natoms,ncoords);
339   else {*/
340     /* make space for coordinates and velocities */
341     init_t_atoms(&confat,natoms,FALSE);
342     printf("init_t\n");
343     snew(*x,natoms);
344     read_stx_conf(confin,title,&confat,*x,NULL,NULL,box);
345     return natoms;
346 }  
347
348
349 void read_eigenvalues(int vecs[],const char *eigfile, real values[], 
350                       gmx_bool bHesse, real kT) 
351 {
352   int  neig,nrow,i;
353   double **eigval;
354   
355   neig = read_xvg(eigfile,&eigval,&nrow);
356   
357   fprintf(stderr,"Read %d eigenvalues\n",neig);
358   for(i=bHesse ? 6 : 0 ; i<neig; i++) { 
359     if (eigval[1][i] < -0.001 && bHesse)
360       fprintf(stderr,
361               "WARNING: The Hessian Matrix has negative eigenvalue %f, we set it to zero (no flooding in this direction)\n\n",eigval[1][i]);
362       
363     if (eigval[1][i] < 0)
364       eigval[1][i] = 0;
365   }
366   if (bHesse)
367     for (i=0; vecs[i]; i++) {
368       if (vecs[i]<7)
369         gmx_fatal(FARGS,"ERROR: You have chosen one of the first 6 eigenvectors of the HESSE Matrix. That does not make sense, since they correspond to the 6 rotational and translational degrees of freedom.\n\n");
370       values[i]=eigval[1][vecs[i]-1]/kT;
371     }
372   else
373     for (i=0; vecs[i]; i++) {
374       if (vecs[i]>(neig-6))
375         gmx_fatal(FARGS,"ERROR: You have chosen one of the last 6 eigenvectors of the COVARIANCE Matrix. That does not make sense, since they correspond to the 6 rotational and translational degrees of freedom.\n\n");
376       values[i]=1/eigval[1][vecs[i]-1];
377     }
378   /* free memory */
379   for (i=0; i<nrow; i++)
380     sfree(eigval[i]);
381   sfree(eigval);
382 }
383
384
385 static real *scan_vecparams(const char *str,const char * par, int nvecs)
386 {
387   char   f0[256],f1[256];             /*format strings adapted every pass of the loop*/
388   double d,tcap=0;
389   int    i;
390   real   *vec_params;
391
392   snew(vec_params,nvecs);
393   if (str) {
394     f0[0] = '\0';
395     for(i=0; (i<nvecs); i++) {
396       strcpy(f1,f0);  /*f0 is the format string for the "to-be-ignored" numbers*/
397       strcat(f1,"%lf"); /*and f1 to read the actual number in this pass of the loop*/
398       if (sscanf(str,f1,&d) != 1)
399         gmx_fatal(FARGS,"Not enough elements for %s parameter (I need %d)",par,nvecs);
400       vec_params[i] = d;
401       tcap += d;
402       strcat(f0,"%*s");
403     }
404   }  
405   return vec_params;
406 }    
407
408
409 void init_edx(struct edix *edx) {
410   edx->nr=0;
411   snew(edx->x,1);
412   snew(edx->anrs,1);
413 }
414
415 void filter2edx(struct edix *edx,int nindex, atom_id index[],int ngro, 
416                 atom_id igro[],rvec *x,const char* structure) 
417 {
418 /* filter2edx copies coordinates from x to edx which are given in index
419 */
420   
421    int pos,i;
422    int ix=edx->nr;
423    edx->nr+=nindex;
424    srenew(edx->x,edx->nr);
425    srenew(edx->anrs,edx->nr);
426    for (i=0;i<nindex;i++,ix++) {
427          for (pos=0; pos<ngro-1 && igro[pos]!=index[i] ; ++pos) {};  /*search element in igro*/
428          if (igro[pos]!=index[i])
429               gmx_fatal(FARGS,"Couldn't find atom with index %d in structure %s",index[i],structure);
430          edx->anrs[ix]=index[i];
431          copy_rvec(x[pos],edx->x[ix]);
432    }
433 }
434
435 void get_structure(t_atoms *atoms,const char *IndexFile,
436                    const char *StructureFile,struct edix *edx,int nfit,
437                    atom_id ifit[],int natoms, atom_id index[]) 
438 {
439   atom_id *igro;  /*index corresponding to target or origin structure*/
440   int ngro;
441   int ntar;
442   rvec *xtar;
443   char  title[STRLEN];
444   char* grpname;
445   
446
447   ntar=read_conffile(StructureFile,title,&xtar);
448   printf("Select an index group of %d elements that corresponds to the atoms in the structure file %s\n",
449             ntar,StructureFile);
450   get_index(atoms,IndexFile,1,&ngro,&igro,&grpname);
451   if (ngro!=ntar)
452      gmx_fatal(FARGS,"You selected an index group with %d elements instead of %d",ngro,ntar);
453   init_edx(edx);
454   filter2edx(edx,nfit,ifit,ngro,igro,xtar,StructureFile);
455   if (ifit!=index) /*if fit structure is different append these coordinates, too -- don't mind duplicates*/
456      filter2edx(edx,natoms,index,ngro,igro,xtar,StructureFile);
457 }
458
459 int main(int argc,char *argv[])
460 {
461
462   static const char *desc[] = {
463       "[TT]make_edi[tt] generates an essential dynamics (ED) sampling input file to be used with [TT]mdrun[tt]",
464       "based on eigenvectors of a covariance matrix ([TT]g_covar[tt]) or from a", 
465       "normal modes anaysis ([TT]g_nmeig[tt]).",
466       "ED sampling can be used to manipulate the position along collective coordinates",
467       "(eigenvectors) of (biological) macromolecules during a simulation. Particularly,",
468       "it may be used to enhance the sampling efficiency of MD simulations by stimulating",
469       "the system to explore new regions along these collective coordinates. A number",
470       "of different algorithms are implemented to drive the system along the eigenvectors",
471       "([TT]-linfix[tt], [TT]-linacc[tt], [TT]-radfix[tt], [TT]-radacc[tt], [TT]-radcon[tt]),",
472       "to keep the position along a certain (set of) coordinate(s) fixed ([TT]-linfix[tt]),",
473       "or to only monitor the projections of the positions onto",
474       "these coordinates ([TT]-mon[tt]).[PAR]",
475       "References:[BR]",
476       "A. Amadei, A.B.M. Linssen, B.L. de Groot, D.M.F. van Aalten and ",
477       "H.J.C. Berendsen; An efficient method for sampling the essential subspace ",
478       "of proteins., J. Biomol. Struct. Dyn. 13:615-626 (1996)[BR]",
479       "B.L. de Groot, A. Amadei, D.M.F. van Aalten and H.J.C. Berendsen; ",
480       "Towards an exhaustive sampling of the configurational spaces of the ",
481       "two forms of the peptide hormone guanylin,",
482       "J. Biomol. Struct. Dyn. 13 : 741-751 (1996)[BR]",
483       "B.L. de Groot, A.Amadei, R.M. Scheek, N.A.J. van Nuland and H.J.C. Berendsen; ",
484       "An extended sampling of the configurational space of HPr from E. coli",
485       "PROTEINS: Struct. Funct. Gen. 26: 314-322 (1996)",
486       "[PAR]You will be prompted for one or more index groups that correspond to the eigenvectors,",
487       "reference structure, target positions, etc.[PAR]",
488       
489       "[TT]-mon[tt]: monitor projections of the coordinates onto selected eigenvectors.[PAR]",
490       "[TT]-linfix[tt]: perform fixed-step linear expansion along selected eigenvectors.[PAR]",
491       "[TT]-linacc[tt]: perform acceptance linear expansion along selected eigenvectors.",
492       "(steps in the desired directions will be accepted, others will be rejected).[PAR]",
493       "[TT]-radfix[tt]: perform fixed-step radius expansion along selected eigenvectors.[PAR]",
494       "[TT]-radacc[tt]: perform acceptance radius expansion along selected eigenvectors.",
495       "(steps in the desired direction will be accepted, others will be rejected).",
496       "Note: by default the starting MD structure will be taken as origin of the first",
497       "expansion cycle for radius expansion. If [TT]-ori[tt] is specified, you will be able",
498       "to read in a structure file that defines an external origin.[PAR]",
499       "[TT]-radcon[tt]: perform acceptance radius contraction along selected eigenvectors",
500       "towards a target structure specified with [TT]-tar[tt].[PAR]",
501       "NOTE: each eigenvector can be selected only once. [PAR]",
502       "[TT]-outfrq[tt]: frequency (in steps) of writing out projections etc. to .edo file[PAR]",
503       "[TT]-slope[tt]: minimal slope in acceptance radius expansion. A new expansion",
504       "cycle will be started if the spontaneous increase of the radius (in nm/step)",
505       "is less than the value specified.[PAR]",
506       "[TT]-maxedsteps[tt]: maximum number of steps per cycle in radius expansion",
507       "before a new cycle is started.[PAR]",
508       "Note on the parallel implementation: since ED sampling is a 'global' thing",
509       "(collective coordinates etc.), at least on the 'protein' side, ED sampling",
510       "is not very parallel-friendly from an implentation point of view. Because",
511       "parallel ED requires much extra communication, expect the performance to be",
512       "lower as in a free MD simulation, especially on a large number of nodes. [PAR]",
513       "All output of [TT]mdrun[tt] (specify with [TT]-eo[tt]) is written to a .edo file. In the output",
514       "file, per OUTFRQ step the following information is present: [PAR]",
515       "* the step number[BR]",
516       "* the number of the ED dataset. (Note that you can impose multiple ED constraints in",
517       "a single simulation - on different molecules e.g. - if several .edi files were concatenated",
518       "first. The constraints are applied in the order they appear in the .edi file.) [BR]",
519       "* RMSD (for atoms involved in fitting prior to calculating the ED constraints)[BR]",
520       "* projections of the positions onto selected eigenvectors[BR]",
521       "[PAR][PAR]",
522       "FLOODING:[PAR]",
523       "with -flood you can specify which eigenvectors are used to compute a flooding potential,",
524       "which will lead to extra forces expelling the structure out of the region described",
525       "by the covariance matrix. If you switch -restrain the potential is inverted and the structure",
526       "is kept in that region.",
527       "[PAR]",
528       "The origin is normally the average structure stored in the eigvec.trr file.",
529       "It can be changed with -ori to an arbitrary position in configurational space.",
530       "With -tau, -deltaF0 and -Eflnull you control the flooding behaviour.",
531       "Efl is the flooding strength, it is updated according to the rule of adaptive flooding.",
532       "Tau is the time constant of adaptive flooding, high tau means slow adaption (i.e. growth). ",
533       "DeltaF0 is the flooding strength you want to reach after tau ps of simulation.",
534       "To use constant Efl set -tau to zero.",
535       "[PAR]",
536       "-alpha is a fudge parameter to control the width of the flooding potential. A value of 2 has been found",
537       "to give good results for most standard cases in flooding of proteins.",
538       "Alpha basically accounts for incomplete sampling, if you sampled further the width of the ensemble would",
539       "increase, this is mimicked by alpha>1.",
540       "For restraining alpha<1 can give you smaller width in the restraining potential.",
541       "[PAR]",
542       "RESTART and FLOODING:",
543       "If you want to restart a crashed flooding simulation please find the values deltaF and Efl in",
544       "the output file and manually put them into the .edi file under DELTA_F0 and EFL_NULL."
545   };
546     
547     /* Save all the params in this struct and then save it in an edi file.
548     * ignoring fields nmass,massnrs,mass,tmass,nfit,fitnrs,edo
549     */
550     static t_edipar edi_params;     
551     
552     enum  { evSTEPEND = evRADFIX + 1}; 
553     static const char* evSelections[evEND]= {NULL,NULL,NULL,NULL,NULL,NULL};
554     static const char* evOptions[evEND] = {"-linfix","-linacc","-flood","-radfix","-radacc","-radcon","-mon"};
555     static const char* evParams[evSTEPEND] ={NULL,NULL};
556     static const char* evStepOptions[evSTEPEND] = {"-linstep","-accdir","-not_used","-radstep"};
557     static real* evStepList[evSTEPEND];
558     static real  radfix=0.0;
559     static real deltaF0=150;
560     static real deltaF=0;
561     static real tau=.1;
562     static real constEfl=0.0;
563     static real alpha=1;
564     static int eqSteps=0;
565     static int* listen[evEND];
566     static real T=300.0;
567     const real kB = 2.5 / 300.0; /* k_boltzmann in MD units */
568     static gmx_bool bRestrain = FALSE;
569     static gmx_bool bHesse=FALSE;
570     static gmx_bool bHarmonic=FALSE;
571     t_pargs pa[] = {
572     { "-mon", FALSE, etSTR, {&evSelections[evMON]},
573         "Indices of eigenvectors for projections of x (e.g. 1,2-5,9) or 1-100:10 means 1 11 21 31 ... 91" },
574     { "-linfix", FALSE, etSTR, {&evSelections[0]},
575         "Indices of eigenvectors for fixed increment linear sampling" },
576     { "-linacc", FALSE, etSTR, {&evSelections[1]},
577         "Indices of eigenvectors for acceptance linear sampling" },
578     { "-flood",  FALSE, etSTR, {&evSelections[2]},
579         "Indices of eigenvectors for flooding"},
580     { "-radfix", FALSE, etSTR, {&evSelections[3]},
581         "Indices of eigenvectors for fixed increment radius expansion" },
582     { "-radacc", FALSE, etSTR, {&evSelections[4]},
583         "Indices of eigenvectors for acceptance radius expansion" },
584     { "-radcon", FALSE, etSTR, {&evSelections[5]},
585         "Indices of eigenvectors for acceptance radius contraction" },
586     { "-outfrq", FALSE, etINT, {&edi_params.outfrq},
587         "Freqency (in steps) of writing output in [TT].edo[tt] file" },
588     { "-slope", FALSE, etREAL, { &edi_params.slope},
589         "Minimal slope in acceptance radius expansion"},
590     { "-maxedsteps", FALSE, etINT, {&edi_params.maxedsteps},
591         "Max nr of steps per cycle" },
592     { "-deltaF0", FALSE,etREAL, {&deltaF0},
593         "Target destabilization energy  - used for flooding"},
594     { "-deltaF", FALSE, etREAL, {&deltaF},
595         "Start deltaF with this parameter - default 0, i.e. nonzero values only needed for restart"},
596     { "-tau", FALSE, etREAL, {&tau}, 
597         "Coupling constant for adaption of flooding strength according to deltaF0, 0 = infinity i.e. constant flooding strength"},
598     { "-eqsteps", FALSE, etINT, {&eqSteps},
599         "Number of steps to run without any perturbations "},
600     { "-Eflnull", FALSE, etREAL, {&constEfl},
601         "This is the starting value of the flooding strength. The flooding strength is updated according to the adaptive flooding scheme. To use a constant flooding strength use [TT]-tau[tt] 0. "},
602     { "-T", FALSE, etREAL, {&T},
603         "T is temperature, the value is needed if you want to do flooding "},
604     { "-alpha",FALSE,etREAL,{&alpha},
605         "Scale width of gaussian flooding potential with alpha^2 "},
606     { "-linstep", FALSE, etSTR, {&evParams[0]},
607       "Stepsizes (nm/step) for fixed increment linear sampling (put in quotes! \"1.0 2.3 5.1 -3.1\")"},
608     { "-accdir", FALSE, etSTR, {&evParams[1]},
609       "Directions for acceptance linear sampling - only sign counts! (put in quotes! \"-1 +1 -1.1\")"},
610     { "-radstep", FALSE, etREAL, {&radfix},
611         "Stepsize (nm/step) for fixed increment radius expansion"},
612     { "-restrain",FALSE, etBOOL, {&bRestrain},
613         "Use the flooding potential with inverted sign -> effects as quasiharmonic restraining potential"},
614     { "-hessian",FALSE, etBOOL, {&bHesse},
615         "The eigenvectors and eigenvalues are from a Hessian matrix"},
616     { "-harmonic",FALSE, etBOOL, {&bHarmonic}, 
617         "The eigenvalues are interpreted as spring constant"},
618     };
619 #define NPA asize(pa)
620     
621     rvec       *xref1;
622     int        nvec1,*eignr1=NULL;
623     rvec       *xav1,**eigvec1=NULL;
624     t_atoms    *atoms=NULL;
625     int natoms;
626     char       *grpname;
627     const char *indexfile;
628     int        i;
629     atom_id    *index,*ifit;
630     int        nfit;
631     int ev_class; /* parameter _class i.e. evMON, evRADFIX etc. */
632     int nvecs;
633     real *eigval1=NULL; /* in V3.3 this is parameter of read_eigenvectors */
634     
635     const char *EdiFile;
636     const char *TargetFile;
637     const char *OriginFile;
638     const char *EigvecFile;
639    
640     output_env_t oenv;
641     
642     /*to read topology file*/
643     t_topology top;
644     int        ePBC;
645     char       title[STRLEN];
646     matrix     topbox;
647     rvec       *xtop;
648     gmx_bool bTop, bFit1;
649     
650     t_filenm fnm[] = {
651     { efTRN, "-f",    "eigenvec",    ffREAD  },
652     { efXVG, "-eig",  "eigenval",    ffOPTRD }, 
653     { efTPS, NULL,    NULL,          ffREAD },
654     { efNDX, NULL,    NULL,  ffOPTRD },
655     { efSTX, "-tar", "target", ffOPTRD},
656     { efSTX, "-ori", "origin", ffOPTRD},
657     { efEDI, "-o", "sam", ffWRITE }
658     };
659 #define NFILE asize(fnm)
660     edi_params.outfrq=100; edi_params.slope=0.0; edi_params.maxedsteps=0;
661     CopyRight(stderr,argv[0]);
662     parse_common_args(&argc,argv, 0 ,
663                       NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL,&oenv);
664     
665     indexfile=ftp2fn_null(efNDX,NFILE,fnm);
666     EdiFile=ftp2fn(efEDI,NFILE,fnm);
667     TargetFile      = opt2fn_null("-tar",NFILE,fnm);
668     OriginFile      = opt2fn_null("-ori",NFILE,fnm);
669     
670     
671     for (ev_class=0; ev_class<evEND; ++ev_class) {
672         if (opt2parg_bSet(evOptions[ev_class],NPA,pa)) {
673             /*get list of eigenvectors*/
674             nvecs=sscan_list(&(listen[ev_class]),opt2parg_str(evOptions[ev_class],NPA,pa),evOptions[ev_class]);
675             if (ev_class<evSTEPEND-2) {
676                 /*if apropriate get list of stepsizes for these eigenvectors*/
677                 if (opt2parg_bSet(evStepOptions[ev_class],NPA,pa)) 
678                     evStepList[ev_class]=
679                         scan_vecparams(opt2parg_str(evStepOptions[ev_class],NPA,pa),evStepOptions[ev_class],nvecs);
680                 else { /*if list is not given fill with zeros */
681                     snew(evStepList[ev_class],nvecs);
682                     for (i=0; i<nvecs; i++) 
683                         evStepList[ev_class][i]=0.0;
684                 }
685             } else if (ev_class == evRADFIX && opt2parg_bSet(evStepOptions[ev_class],NPA,pa)) {
686                 snew(evStepList[ev_class],nvecs);
687                 for (i=0; i<nvecs; i++)
688                     evStepList[ev_class][i]=radfix;
689                 
690             } else if (ev_class == evFLOOD) {
691                 snew(evStepList[ev_class],nvecs);
692             } else {}; /*to avoid ambiguity   */
693         } else { /* if there are no eigenvectors for this option set list to zero */
694             listen[ev_class]=NULL;
695             snew(listen[ev_class],1);
696             listen[ev_class][0]=0;
697         };
698     };
699     
700     /* print the interpreted list of eigenvectors - to give some feedback*/
701     for (ev_class=0; ev_class<evEND; ++ev_class) {
702         printf("list %s consist of the indices:",evOptions[ev_class]);
703         i=0;
704         while(listen[ev_class][i])
705             printf("%d ",listen[ev_class][i++]);
706         printf("\n");
707     }
708     
709     EigvecFile=NULL; 
710     EigvecFile=opt2fn("-f",NFILE,fnm); 
711     
712     
713     /*read eigenvectors from eigvec.trr*/
714     read_eigenvectors(EigvecFile,&natoms,&bFit1,
715                       &xref1,&edi_params.fitmas,&xav1,&edi_params.pcamas,&nvec1,&eignr1,&eigvec1,&eigval1);
716            
717     bTop=read_tps_conf(ftp2fn(efTPS,NFILE,fnm),
718                        title,&top,&ePBC,&xtop,NULL,topbox,0);
719     atoms=&top.atoms;
720     
721     
722     printf("\nSelect an index group of %d elements that corresponds to the eigenvectors\n",natoms);
723     get_index(atoms,indexfile,1,&i,&index,&grpname); /*if indexfile != NULL parameter 'atoms' is ignored */
724     if (i!=natoms) {
725         gmx_fatal(FARGS,"you selected a group with %d elements instead of %d",
726                   i,natoms);
727     }
728     printf("\n");
729     
730     
731     if (xref1==NULL)
732     {
733         if (bFit1)
734         {
735             /* if g_covar used different coordinate groups to fit and to do the PCA */
736             printf("\nNote: the structure in %s should be the same\n"
737                      "      as the one used for the fit in g_covar\n",ftp2fn(efTPS,NFILE,fnm));
738             printf("\nSelect the index group that was used for the least squares fit in g_covar\n");
739         }
740         else
741         {
742             printf("\nNote: Apparently no fitting was done in g_covar.\n"
743                      "      However, you need to select a reference group for fitting in mdrun\n");
744         }
745         get_index(atoms,indexfile,1,&nfit,&ifit,&grpname);
746         snew(xref1,nfit);
747         for (i=0;i<nfit;i++)
748             copy_rvec(xtop[ifit[i]],xref1[i]);
749     }
750     else
751     {
752         nfit=natoms;
753         ifit=index;
754     }
755
756     /* if -flood read eigenvalues and store them in evSteplist[evFLOOD] */
757     if (listen[evFLOOD][0]!=0)
758         read_eigenvalues(listen[evFLOOD],opt2fn("-eig",NFILE,fnm),evStepList[evFLOOD],bHesse,kB*T);
759  
760   /*number of eigenvectors*/
761   edi_params.ned=natoms;
762   edi_params.flood.tau=tau;
763   edi_params.flood.deltaF0=deltaF0;
764   edi_params.flood.deltaF=deltaF;
765   edi_params.presteps=eqSteps;
766   edi_params.flood.kT=kB*T;
767   edi_params.flood.bHarmonic=bHarmonic;
768   if (bRestrain)
769   {
770       /* Trick: invert sign of Efl and alpha2 then this will give the same sign in the exponential and inverted sign outside */
771       edi_params.flood.constEfl=-constEfl;
772       edi_params.flood.alpha2=-sqr(alpha);
773   }
774   else
775   {
776       edi_params.flood.constEfl=constEfl;
777       edi_params.flood.alpha2=sqr(alpha);
778   }
779   
780   /*number of system atoms  */
781   edi_params.nini=atoms->nr;
782
783  
784   /*store reference and average structure in edi_params*/
785   make_t_edx(&edi_params.sref,nfit,xref1,ifit);
786   make_t_edx(&edi_params.sav,natoms,xav1,index);
787
788                                                          
789   /*store target positions in edi_params*/
790   if (opt2bSet("-tar",NFILE,fnm)) {
791     get_structure(atoms,indexfile,TargetFile,&edi_params.star,nfit,
792                    ifit,natoms,index);
793  } else
794       make_t_edx(&edi_params.star,0,NULL,index);
795      /*store origin positions*/
796  if (opt2bSet("-ori",NFILE,fnm)) {
797      get_structure(atoms,indexfile,OriginFile,&edi_params.sori,nfit,
798                    ifit,natoms,index);
799  } else
800       make_t_edx(&edi_params.sori,0,NULL,index);
801   
802   /*write edi-file*/
803   write_the_whole_thing(ffopen(EdiFile,"w"), &edi_params, eigvec1,nvec1, listen, evStepList);
804   thanx(stderr);
805   return 0;
806 }
807