Don't use POSIX fnmatch() for pattern matching.
[gromacs/qmmm-gamess-us.git] / src / tools / gmx_eneconv.c
blobdd9494191be9eb2555599667d1af86735a958402
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 * 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
32 * And Hey:
33 * Green Red Orange Magenta Azure Cyan Skyblue
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38 #include <string.h>
39 #include <math.h>
41 #include "string2.h"
42 #include "typedefs.h"
43 #include "smalloc.h"
44 #include "statutil.h"
45 #include "disre.h"
46 #include "names.h"
47 #include "copyrite.h"
48 #include "macros.h"
49 #include "gmx_fatal.h"
50 #include "enxio.h"
51 #include "vec.h"
53 #define TIME_EXPLICIT 0
54 #define TIME_CONTINUE 1
55 #define TIME_LAST 2
56 #ifndef FLT_MAX
57 #define FLT_MAX 1e36
58 #endif
60 static int *select_it(int nre,gmx_enxnm_t *nm,int *nset)
62 bool *bE;
63 int n,k,j,i;
64 int *set;
65 bool bVerbose = TRUE;
67 if ((getenv("VERBOSE")) != NULL)
68 bVerbose = FALSE;
70 fprintf(stderr,"Select the terms you want to scale from the following list\n");
71 fprintf(stderr,"End your selection with 0\n");
73 if ( bVerbose ) {
74 for(k=0; (k<nre); ) {
75 for(j=0; (j<4) && (k<nre); j++,k++)
76 fprintf(stderr," %3d=%14s",k+1,nm[k].name);
77 fprintf(stderr,"\n");
81 snew(bE,nre);
82 do {
83 if(1 != scanf("%d",&n))
85 gmx_fatal(FARGS,"Cannot read energy term");
87 if ((n>0) && (n<=nre))
88 bE[n-1]=TRUE;
89 } while (n != 0);
91 snew(set,nre);
92 for(i=(*nset)=0; (i<nre); i++)
93 if (bE[i])
94 set[(*nset)++]=i;
96 sfree(bE);
98 return set;
101 static bool same_time(real t1,real t2)
103 const real tol=1e-5;
105 return (fabs(t1-t2) < tol);
109 bool bRgt(double a,double b)
111 double tol = 1e-6;
113 if ( a > (b - tol*(a+b)) )
114 return TRUE;
115 else
116 return FALSE;
119 static void sort_files(char **fnms,real *settime,int nfile)
121 int i,j,minidx;
122 real timeswap;
123 char *chptr;
125 for(i=0;i<nfile;i++) {
126 minidx=i;
127 for(j=i+1;j<nfile;j++) {
128 if(settime[j]<settime[minidx])
129 minidx=j;
131 if(minidx!=i) {
132 timeswap=settime[i];
133 settime[i]=settime[minidx];
134 settime[minidx]=timeswap;
135 chptr=fnms[i];
136 fnms[i]=fnms[minidx];
137 fnms[minidx]=chptr;
143 static int scan_ene_files(char **fnms, int nfiles,
144 real *readtime, real *timestep, int *nremax)
146 /* Check number of energy terms and start time of all files */
147 int f,i,nre,nremin=0,nresav=0;
148 ener_file_t in;
149 real t1,t2;
150 char inputstring[STRLEN];
151 gmx_enxnm_t *enm;
152 t_enxframe *fr;
154 snew(fr,1);
156 for(f=0; f<nfiles; f++) {
157 in = open_enx(fnms[f],"r");
158 enm = NULL;
159 do_enxnms(in,&nre,&enm);
161 if (f == 0) {
162 nresav = nre;
163 nremin = nre;
164 *nremax = nre;
165 do_enx(in,fr);
166 t1 = fr->t;
167 do_enx(in,fr);
168 t2 = fr->t;
169 *timestep=t2-t1;
170 readtime[f]=t1;
171 close_enx(in);
172 } else {
173 nremin = min(nremin,fr->nre);
174 *nremax = max(*nremax,fr->nre);
175 if (nre != nresav) {
176 fprintf(stderr,
177 "Energy files don't match, different number of energies:\n"
178 " %s: %d\n %s: %d\n",fnms[f-1],nresav,fnms[f],fr->nre);
179 fprintf(stderr,
180 "\nContinue conversion using only the first %d terms (n/y)?\n"
181 "(you should be sure that the energy terms match)\n",nremin);
182 if(NULL==fgets(inputstring,STRLEN-1,stdin))
184 gmx_fatal(FARGS,"Error reading user input");
186 if (inputstring[0]!='y' && inputstring[0]!='Y') {
187 fprintf(stderr,"Will not convert\n");
188 exit(0);
190 nresav = fr->nre;
192 do_enx(in,fr);
193 readtime[f] = fr->t;
194 close_enx(in);
196 fprintf(stderr,"\n");
197 free_enxnms(nre,enm);
200 free_enxframe(fr);
201 sfree(fr);
203 return nremin;
207 static void edit_files(char **fnms,int nfiles,real *readtime,
208 real *settime,int *cont_type,bool bSetTime,bool bSort)
210 int i;
211 bool ok;
212 char inputstring[STRLEN],*chptr;
214 if(bSetTime) {
215 if(nfiles==1)
216 fprintf(stderr,"\n\nEnter the new start time:\n\n");
217 else
218 fprintf(stderr,"\n\nEnter the new start time for each file.\n"
219 "There are two special options, both disables sorting:\n\n"
220 "c (continue) - The start time is taken from the end\n"
221 "of the previous file. Use it when your continuation run\n"
222 "restarts with t=0 and there is no overlap.\n\n"
223 "l (last) - The time in this file will be changed the\n"
224 "same amount as in the previous. Use it when the time in the\n"
225 "new run continues from the end of the previous one,\n"
226 "since this takes possible overlap into account.\n\n");
228 fprintf(stderr," File Current start New start\n"
229 "---------------------------------------------------------\n");
231 for(i=0;i<nfiles;i++) {
232 fprintf(stderr,"%25s %10.3f ",fnms[i],readtime[i]);
233 ok=FALSE;
234 do {
235 if(NULL==fgets(inputstring,STRLEN-1,stdin))
237 gmx_fatal(FARGS,"Error reading user input");
239 inputstring[strlen(inputstring)-1]=0;
241 if(inputstring[0]=='c' || inputstring[0]=='C') {
242 cont_type[i]=TIME_CONTINUE;
243 bSort=FALSE;
244 ok=TRUE;
245 settime[i]=FLT_MAX;
247 else if(inputstring[0]=='l' ||
248 inputstring[0]=='L') {
249 cont_type[i]=TIME_LAST;
250 bSort=FALSE;
251 ok=TRUE;
252 settime[i]=FLT_MAX;
254 else {
255 settime[i]=strtod(inputstring,&chptr);
256 if(chptr==inputstring) {
257 fprintf(stderr,"Try that again: ");
259 else {
260 cont_type[i]=TIME_EXPLICIT;
261 ok=TRUE;
264 } while (!ok);
266 if(cont_type[0]!=TIME_EXPLICIT) {
267 cont_type[0]=TIME_EXPLICIT;
268 settime[0]=0;
271 else
272 for(i=0;i<nfiles;i++)
273 settime[i]=readtime[i];
275 if(bSort && (nfiles>1))
276 sort_files(fnms,settime,nfiles);
277 else
278 fprintf(stderr,"Sorting disabled.\n");
281 /* Write out the new order and start times */
282 fprintf(stderr,"\nSummary of files and start times used:\n\n"
283 " File Start time\n"
284 "-----------------------------------------\n");
285 for(i=0;i<nfiles;i++)
286 switch(cont_type[i]) {
287 case TIME_EXPLICIT:
288 fprintf(stderr,"%25s %10.3f\n",fnms[i],settime[i]);
289 break;
290 case TIME_CONTINUE:
291 fprintf(stderr,"%25s Continue from end of last file\n",fnms[i]);
292 break;
293 case TIME_LAST:
294 fprintf(stderr,"%25s Change by same amount as last file\n",fnms[i]);
295 break;
297 fprintf(stderr,"\n");
299 settime[nfiles]=FLT_MAX;
300 cont_type[nfiles]=TIME_EXPLICIT;
301 readtime[nfiles]=FLT_MAX;
305 static void copy_ee(t_energy *src, t_energy *dst, int nre)
307 int i;
309 for(i=0;i<nre;i++) {
310 dst[i].e=src[i].e;
311 dst[i].esum=src[i].esum;
312 dst[i].eav=src[i].eav;
317 static void remove_last_eeframe(t_energy *lastee, gmx_large_int_t laststep,
318 t_energy *ee, int nre)
320 int i;
321 gmx_large_int_t p=laststep+1;
322 double sigmacorr;
324 for(i=0;i<nre;i++) {
325 lastee[i].esum-=ee[i].e;
326 sigmacorr=lastee[i].esum-(p-1)*ee[i].e;
327 lastee[i].eav-=(sigmacorr*sigmacorr)/((p-1)*p);
333 static void update_ee(t_energy *lastee,gmx_large_int_t laststep,
334 t_energy *startee,gmx_large_int_t startstep,
335 t_energy *ee, int step,
336 t_energy *outee, int nre)
338 int i;
339 double sigmacorr,nom,denom;
340 double prestart_esum;
341 double prestart_sigma;
343 for(i=0;i<nre;i++) {
344 outee[i].e=ee[i].e;
345 /* add statistics from earlier file if present */
346 if(laststep>0) {
347 outee[i].esum=lastee[i].esum+ee[i].esum;
348 nom=(lastee[i].esum*(step+1)-ee[i].esum*(laststep));
349 denom=((step+1.0)*(laststep)*(step+1.0+laststep));
350 sigmacorr=nom*nom/denom;
351 outee[i].eav=lastee[i].eav+ee[i].eav+sigmacorr;
353 else {
354 /* otherwise just copy to output */
355 outee[i].esum=ee[i].esum;
356 outee[i].eav=ee[i].eav;
359 /* if we didnt start to write at the first frame
360 * we must compensate the statistics for this
361 * there are laststep frames in the earlier file
362 * and step+1 frames in this one.
364 if(startstep>0) {
365 gmx_large_int_t q=laststep+step;
366 gmx_large_int_t p=startstep+1;
367 prestart_esum=startee[i].esum-startee[i].e;
368 sigmacorr=prestart_esum-(p-1)*startee[i].e;
369 prestart_sigma=startee[i].eav-
370 sigmacorr*sigmacorr/(p*(p-1));
371 sigmacorr=prestart_esum/(p-1)-
372 outee[i].esum/(q);
373 outee[i].esum-=prestart_esum;
374 if (q-p+1 > 0)
375 outee[i].eav=outee[i].eav-prestart_sigma-
376 sigmacorr*sigmacorr*((p-1)*q)/(q-p+1);
379 if((outee[i].eav/(laststep+step+1))<(GMX_REAL_EPS))
380 outee[i].eav=0;
385 static void update_last_ee(t_energy *lastee, gmx_large_int_t laststep,
386 t_energy *ee,gmx_large_int_t step,int nre)
388 t_energy *tmp;
389 snew(tmp,nre);
390 update_ee(lastee,laststep,NULL,0,ee,step,tmp,nre);
391 copy_ee(tmp,lastee,nre);
392 sfree(tmp);
395 static void update_ee_sum(int nre,
396 gmx_large_int_t *ee_sum_step,
397 gmx_large_int_t *ee_sum_nsteps,
398 gmx_large_int_t *ee_sum_nsum,
399 t_energy *ee_sum,
400 t_enxframe *fr,int out_step)
402 gmx_large_int_t nsteps,nsum,fr_nsum;
403 int i;
405 nsteps = *ee_sum_nsteps;
406 nsum = *ee_sum_nsum;
408 fr_nsum = fr->nsum;
409 if (fr_nsum == 0) {
410 fr_nsum = 1;
413 if (nsteps == 0) {
414 if (fr_nsum == 1) {
415 for(i=0;i<nre;i++) {
416 ee_sum[i].esum = fr->ener[i].e;
417 ee_sum[i].eav = 0;
419 } else {
420 for(i=0;i<nre;i++) {
421 ee_sum[i].esum = fr->ener[i].esum;
422 ee_sum[i].eav = fr->ener[i].eav;
425 nsteps = fr->nsteps;
426 nsum = fr_nsum;
427 } else if (out_step - *ee_sum_step == nsteps + fr->nsteps) {
428 if (fr_nsum == 1) {
429 for(i=0;i<nre;i++) {
430 ee_sum[i].eav +=
431 dsqr(ee_sum[i].esum/nsum
432 - (ee_sum[i].esum + fr->ener[i].e)/(nsum + 1))*nsum*(nsum + 1);
433 ee_sum[i].esum += fr->ener[i].e;
435 } else {
436 for(i=0; i<fr->nre; i++) {
437 ee_sum[i].eav +=
438 fr->ener[i].eav +
439 dsqr(ee_sum[i].esum/nsum
440 - (ee_sum[i].esum + fr->ener[i].esum)/(nsum + fr->nsum))*
441 nsum*(nsum + fr->nsum)/(double)fr->nsum;
442 ee_sum[i].esum += fr->ener[i].esum;
445 nsteps += fr->nsteps;
446 nsum += fr_nsum;
447 } else {
448 if (fr->nsum != 0) {
449 fprintf(stderr,"\nWARNING: missing energy sums at time %f\n",fr->t);
451 nsteps = 0;
452 nsum = 0;
455 *ee_sum_step = out_step;
456 *ee_sum_nsteps = nsteps;
457 *ee_sum_nsum = nsum;
460 int gmx_eneconv(int argc,char *argv[])
462 const char *desc[] = {
463 "With [IT]multiple files[it] specified for the [TT]-f[tt] option:[BR]",
464 "Concatenates several energy files in sorted order.",
465 "In case of double time frames the one",
466 "in the later file is used. By specifying [TT]-settime[tt] you will be",
467 "asked for the start time of each file. The input files are taken",
468 "from the command line,",
469 "such that the command [TT]eneconv -o fixed.edr *.edr[tt] should do",
470 "the trick. [PAR]",
471 "With [IT]one file[it] specified for [TT]-f[tt]:[BR]",
472 "Reads one energy file and writes another, applying the [TT]-dt[tt],",
473 "[TT]-offset[tt], [TT]-t0[tt] and [TT]-settime[tt] options and",
474 "converting to a different format if necessary (indicated by file",
475 "extentions).[PAR]",
476 "[TT]-settime[tt] is applied first, then [TT]-dt[tt]/[TT]-offset[tt]",
477 "followed by [TT]-b[tt] and [TT]-e[tt] to select which frames to write."
479 const char *bugs[] = {
480 "When combining trajectories the sigma and E^2 (necessary for statistics) are not updated correctly. Only the actual energy is correct. One thus has to compute statistics in another way."
482 ener_file_t in=NULL, out=NULL;
483 gmx_enxnm_t *enm=NULL;
484 #if 0
485 ener_file_t in,out=NULL;
486 gmx_enxnm_t *enm=NULL;
487 #endif
488 t_enxframe *fr,*fro;
489 gmx_large_int_t ee_sum_step=0,ee_sum_nsteps,ee_sum_nsum;
490 t_energy *ee_sum;
491 gmx_large_int_t laststep,startstep,startstep_file=0;
492 int noutfr;
493 int nre,nremax,this_nre,nfile,f,i,j,kkk,nset,*set=NULL;
494 real t;
495 char **fnms;
496 real *readtime,*settime,timestep,t1,tadjust;
497 char inputstring[STRLEN],*chptr,buf[22],buf2[22],buf3[22];
498 bool ok;
499 int *cont_type;
500 bool bNewFile,bFirst,bNewOutput;
501 output_env_t oenv;
503 t_filenm fnm[] = {
504 { efEDR, "-f", NULL, ffRDMULT },
505 { efEDR, "-o", "fixed", ffWRITE },
508 #define NFILE asize(fnm)
509 bool bWrite;
510 static real delta_t=0.0, toffset=0,scalefac=1;
511 static bool bSetTime=FALSE;
512 static bool bSort=TRUE,bError=TRUE;
513 static real begin=-1;
514 static real end=-1;
516 t_pargs pa[] = {
517 { "-b", FALSE, etREAL, {&begin},
518 "First time to use"},
519 { "-e", FALSE, etREAL, {&end},
520 "Last time to use"},
521 { "-dt", FALSE, etREAL, {&delta_t},
522 "Only write out frame when t MOD dt = offset" },
523 { "-offset", FALSE, etREAL, {&toffset},
524 "Time offset for -dt option" },
525 { "-settime", FALSE, etBOOL, {&bSetTime},
526 "Change starting time interactively" },
527 { "-sort", FALSE, etBOOL, {&bSort},
528 "Sort energy files (not frames)"},
529 { "-scalefac", FALSE, etREAL, {&scalefac},
530 "Multiply energy component by this factor" },
531 { "-error", FALSE, etBOOL, {&bError},
532 "Stop on errors in the file" }
535 CopyRight(stderr,argv[0]);
536 parse_common_args(&argc,argv,PCA_BE_NICE,NFILE,fnm,asize(pa),
537 pa,asize(desc),desc,asize(bugs),bugs,&oenv);
538 tadjust = 0;
539 nremax = 0;
540 nset = 0;
541 timestep = 0.0;
542 snew(fnms,argc);
543 nfile=0;
544 laststep=startstep=0;
546 nfile = opt2fns(&fnms,"-f",NFILE,fnm);
548 if (!nfile)
549 gmx_fatal(FARGS,"No input files!");
551 snew(settime,nfile+1);
552 snew(readtime,nfile+1);
553 snew(cont_type,nfile+1);
555 nre=scan_ene_files(fnms,nfile,readtime,&timestep,&nremax);
556 edit_files(fnms,nfile,readtime,settime,cont_type,bSetTime,bSort);
558 ee_sum_nsteps = 0;
559 ee_sum_nsum = 0;
560 snew(ee_sum,nremax);
562 snew(fr,1);
563 snew(fro,1);
564 fro->t = -1;
565 fro->nre = nre;
566 snew(fro->ener,nremax);
568 noutfr=0;
569 bFirst=TRUE;
571 t = -1e20;
572 for(f=0;f<nfile;f++) {
573 bNewFile=TRUE;
574 bNewOutput=TRUE;
575 in=open_enx(fnms[f],"r");
576 enm = NULL;
577 do_enxnms(in,&this_nre,&enm);
578 if (f == 0) {
579 if (scalefac != 1)
580 set = select_it(nre,enm,&nset);
582 /* write names to the output file */
583 out=open_enx(opt2fn("-o",NFILE,fnm),"w");
584 do_enxnms(out,&nre,&enm);
587 /* start reading from the next file */
588 while ((t <= (settime[f+1] + GMX_REAL_EPS)) &&
589 do_enx(in,fr)) {
590 if(bNewFile) {
591 startstep_file = fr->step;
592 tadjust = settime[f] - fr->t;
593 if(cont_type[f+1]==TIME_LAST) {
594 settime[f+1] = readtime[f+1]-readtime[f]+settime[f];
595 cont_type[f+1] = TIME_EXPLICIT;
597 bNewFile = FALSE;
600 if (debug) {
601 fprintf(debug,"fr->step %s, ee_sum_nsteps %s, ee_sum_nsum %s\n",
602 gmx_step_str(fr->step,buf),
603 gmx_step_str(ee_sum_nsteps,buf2),
604 gmx_step_str(ee_sum_nsum,buf3));
607 if (tadjust + fr->t <= t) {
608 /* Skip this frame, since we already have it / past it */
609 continue;
612 fro->step = laststep + fr->step - startstep_file;
613 t = tadjust + fr->t;
615 /*bWrite = ((begin<0 || (begin>=0 && (t >= begin-GMX_REAL_EPS))) &&
616 (end <0 || (end >=0 && (t <= end +GMX_REAL_EPS))) &&
617 (t < settime[i+1]-GMX_REAL_EPS));*/
618 bWrite = ((begin<0 || (begin>=0 && (t >= begin-GMX_REAL_EPS))) &&
619 (end <0 || (end >=0 && (t <= end +GMX_REAL_EPS))) &&
620 (t <= settime[f+1]+0.5*timestep));
622 if (bError)
623 if ((end > 0) && (t > end+GMX_REAL_EPS)) {
624 f = nfile;
625 break;
628 if (t >= begin-GMX_REAL_EPS) {
629 if (bFirst) {
630 bFirst = FALSE;
631 startstep = fr->step;
633 update_ee_sum(nre,&ee_sum_step,&ee_sum_nsteps,&ee_sum_nsum,ee_sum,
634 fr,fro->step);
637 /* determine if we should write it */
638 if (bWrite && (delta_t==0 || bRmod(t,toffset,delta_t))) {
639 fro->t = t;
640 if(bNewOutput) {
641 bNewOutput=FALSE;
642 fprintf(stderr,"\nContinue writing frames from t=%g, step=%s\n",
643 t,gmx_step_str(fro->step,buf));
646 /* Copy the energies */
647 for(i=0; i<nre; i++) {
648 fro->ener[i].e = fr->ener[i].e;
651 fro->nsteps = ee_sum_nsteps;
653 if (ee_sum_nsum <= 1) {
654 fro->nsum = 0;
655 } else {
656 fro->nsum = ee_sum_nsum;
657 /* Copy the energy sums */
658 for(i=0; i<nre; i++) {
659 fro->ener[i].esum = ee_sum[i].esum;
660 fro->ener[i].eav = ee_sum[i].eav;
663 /* We wrote the energies, so reset the counts */
664 ee_sum_nsteps = 0;
665 ee_sum_nsum = 0;
667 if (scalefac != 1) {
668 for(kkk=0; kkk<nset; kkk++) {
669 fro->ener[set[kkk]].e *= scalefac;
670 if (fro->nsum > 0) {
671 fro->ener[set[kkk]].eav *= scalefac*scalefac;
672 fro->ener[set[kkk]].esum *= scalefac;
676 /* Copy restraint stuff */
677 fro->ndisre = fr->ndisre;
678 fro->disre_rm3tav = fr->disre_rm3tav;
679 fro->disre_rt = fr->disre_rt;
680 fro->nblock = fr->nblock;
681 fro->nr = fr->nr;
682 fro->block = fr->block;
684 do_enx(out,fro);
685 if (noutfr % 1000 == 0)
686 fprintf(stderr,"Writing frame time %g ",fro->t);
687 noutfr++;
691 if (nfile > 1) {
692 laststep = fro->step;
693 printf("laststep=%s step=%s\n",
694 gmx_step_str(laststep,buf),gmx_step_str(fro->step,buf2));
697 /* set the next time from the last in previous file */
698 if (cont_type[f+1]==TIME_CONTINUE) {
699 settime[f+1] = fro->t;
700 /* in this case we have already written the last frame of
701 * previous file, so update begin to avoid doubling it
702 * with the start of the next file
704 begin = fro->t+0.5*timestep;
705 /* cont_type[f+1]==TIME_EXPLICIT; */
708 if ((fro->t < end) && (f < nfile-1) &&
709 (fro->t < settime[f+1]-1.5*timestep))
710 fprintf(stderr,
711 "\nWARNING: There might be a gap around t=%g\n",t);
713 /* move energies to lastee */
714 close_enx(in);
715 free_enxnms(this_nre,enm);
717 fprintf(stderr,"\n");
719 if (noutfr == 0)
720 fprintf(stderr,"No frames written.\n");
721 else {
722 fprintf(stderr,"Last frame written was at step %s, time %f\n",
723 gmx_step_str(fro->step,buf),fro->t);
724 fprintf(stderr,"Wrote %d frames\n",noutfr);
727 thanx(stderr);
728 return 0;