3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Green Red Orange Magenta Azure Cyan Skyblue
49 #include "gmx_fatal.h"
53 #define TIME_EXPLICIT 0
54 #define TIME_CONTINUE 1
60 static int *select_it(int nre
,gmx_enxnm_t
*nm
,int *nset
)
67 if ((getenv("VERBOSE")) != NULL
)
70 fprintf(stderr
,"Select the terms you want to scale from the following list\n");
71 fprintf(stderr
,"End your selection with 0\n");
75 for(j
=0; (j
<4) && (k
<nre
); j
++,k
++)
76 fprintf(stderr
," %3d=%14s",k
+1,nm
[k
].name
);
83 if(1 != scanf("%d",&n
))
85 gmx_fatal(FARGS
,"Cannot read energy term");
87 if ((n
>0) && (n
<=nre
))
92 for(i
=(*nset
)=0; (i
<nre
); i
++)
101 static bool same_time(real t1
,real t2
)
105 return (fabs(t1
-t2
) < tol
);
109 bool bRgt(double a
,double b
)
113 if ( a
> (b
- tol
*(a
+b
)) )
119 static void sort_files(char **fnms
,real
*settime
,int nfile
)
125 for(i
=0;i
<nfile
;i
++) {
127 for(j
=i
+1;j
<nfile
;j
++) {
128 if(settime
[j
]<settime
[minidx
])
133 settime
[i
]=settime
[minidx
];
134 settime
[minidx
]=timeswap
;
136 fnms
[i
]=fnms
[minidx
];
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;
150 char inputstring
[STRLEN
];
156 for(f
=0; f
<nfiles
; f
++) {
157 in
= open_enx(fnms
[f
],"r");
159 do_enxnms(in
,&nre
,&enm
);
173 nremin
= min(nremin
,fr
->nre
);
174 *nremax
= max(*nremax
,fr
->nre
);
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
);
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");
196 fprintf(stderr
,"\n");
197 free_enxnms(nre
,enm
);
207 static void edit_files(char **fnms
,int nfiles
,real
*readtime
,
208 real
*settime
,int *cont_type
,bool bSetTime
,bool bSort
)
212 char inputstring
[STRLEN
],*chptr
;
216 fprintf(stderr
,"\n\nEnter the new start time:\n\n");
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
]);
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
;
247 else if(inputstring
[0]=='l' ||
248 inputstring
[0]=='L') {
249 cont_type
[i
]=TIME_LAST
;
255 settime
[i
]=strtod(inputstring
,&chptr
);
256 if(chptr
==inputstring
) {
257 fprintf(stderr
,"Try that again: ");
260 cont_type
[i
]=TIME_EXPLICIT
;
266 if(cont_type
[0]!=TIME_EXPLICIT
) {
267 cont_type
[0]=TIME_EXPLICIT
;
272 for(i
=0;i
<nfiles
;i
++)
273 settime
[i
]=readtime
[i
];
275 if(bSort
&& (nfiles
>1))
276 sort_files(fnms
,settime
,nfiles
);
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"
284 "-----------------------------------------\n");
285 for(i
=0;i
<nfiles
;i
++)
286 switch(cont_type
[i
]) {
288 fprintf(stderr
,"%25s %10.3f\n",fnms
[i
],settime
[i
]);
291 fprintf(stderr
,"%25s Continue from end of last file\n",fnms
[i
]);
294 fprintf(stderr
,"%25s Change by same amount as last file\n",fnms
[i
]);
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
)
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
)
321 gmx_large_int_t p
=laststep
+1;
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
)
339 double sigmacorr
,nom
,denom
;
340 double prestart_esum
;
341 double prestart_sigma
;
345 /* add statistics from earlier file if present */
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
;
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.
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)-
373 outee
[i
].esum
-=prestart_esum
;
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
))
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
)
390 update_ee(lastee
,laststep
,NULL
,0,ee
,step
,tmp
,nre
);
391 copy_ee(tmp
,lastee
,nre
);
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
,
400 t_enxframe
*fr
,int out_step
)
402 gmx_large_int_t nsteps
,nsum
,fr_nsum
;
405 nsteps
= *ee_sum_nsteps
;
416 ee_sum
[i
].esum
= fr
->ener
[i
].e
;
421 ee_sum
[i
].esum
= fr
->ener
[i
].esum
;
422 ee_sum
[i
].eav
= fr
->ener
[i
].eav
;
427 } else if (out_step
- *ee_sum_step
== nsteps
+ fr
->nsteps
) {
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
;
436 for(i
=0; i
<fr
->nre
; i
++) {
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
;
449 fprintf(stderr
,"\nWARNING: missing energy sums at time %f\n",fr
->t
);
455 *ee_sum_step
= out_step
;
456 *ee_sum_nsteps
= nsteps
;
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",
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",
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
;
485 ener_file_t in
,out
=NULL
;
486 gmx_enxnm_t
*enm
=NULL
;
489 gmx_large_int_t ee_sum_step
=0,ee_sum_nsteps
,ee_sum_nsum
;
491 gmx_large_int_t laststep
,startstep
,startstep_file
=0;
493 int nre
,nremax
,this_nre
,nfile
,f
,i
,j
,kkk
,nset
,*set
=NULL
;
496 real
*readtime
,*settime
,timestep
,t1
,tadjust
;
497 char inputstring
[STRLEN
],*chptr
,buf
[22],buf2
[22],buf3
[22];
500 bool bNewFile
,bFirst
,bNewOutput
;
504 { efEDR
, "-f", NULL
, ffRDMULT
},
505 { efEDR
, "-o", "fixed", ffWRITE
},
508 #define NFILE asize(fnm)
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;
517 { "-b", FALSE
, etREAL
, {&begin
},
518 "First time to use"},
519 { "-e", FALSE
, etREAL
, {&end
},
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
);
544 laststep
=startstep
=0;
546 nfile
= opt2fns(&fnms
,"-f",NFILE
,fnm
);
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
,×tep
,&nremax
);
556 edit_files(fnms
,nfile
,readtime
,settime
,cont_type
,bSetTime
,bSort
);
566 snew(fro
->ener
,nremax
);
572 for(f
=0;f
<nfile
;f
++) {
575 in
=open_enx(fnms
[f
],"r");
577 do_enxnms(in
,&this_nre
,&enm
);
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
)) &&
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
;
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 */
612 fro
->step
= laststep
+ fr
->step
- startstep_file
;
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
));
623 if ((end
> 0) && (t
> end
+GMX_REAL_EPS
)) {
628 if (t
>= begin
-GMX_REAL_EPS
) {
631 startstep
= fr
->step
;
633 update_ee_sum(nre
,&ee_sum_step
,&ee_sum_nsteps
,&ee_sum_nsum
,ee_sum
,
637 /* determine if we should write it */
638 if (bWrite
&& (delta_t
==0 || bRmod(t
,toffset
,delta_t
))) {
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) {
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 */
668 for(kkk
=0; kkk
<nset
; kkk
++) {
669 fro
->ener
[set
[kkk
]].e
*= scalefac
;
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
;
682 fro
->block
= fr
->block
;
685 if (noutfr
% 1000 == 0)
686 fprintf(stderr
,"Writing frame time %g ",fro
->t
);
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
))
711 "\nWARNING: There might be a gap around t=%g\n",t
);
713 /* move energies to lastee */
715 free_enxnms(this_nre
,enm
);
717 fprintf(stderr
,"\n");
720 fprintf(stderr
,"No frames written.\n");
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
);