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