Fixed make_edi.c
[gromacs/rigid-bodies.git] / src / tools / gmx_energy.c
blob967ef43a6bb1bf1c5254283bb5301b4dc5870135
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 3.2.0
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
33 * And Hey:
34 * Green Red Orange Magenta Azure Cyan Skyblue
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
40 #include <string.h>
41 #include <math.h>
42 #include <ctype.h>
44 #include "typedefs.h"
45 #include "gmx_fatal.h"
46 #include "vec.h"
47 #include "string2.h"
48 #include "smalloc.h"
49 #include "enxio.h"
50 #include "statutil.h"
51 #include "names.h"
52 #include "copyrite.h"
53 #include "macros.h"
54 #include "xvgr.h"
55 #include "gstat.h"
56 #include "physics.h"
57 #include "tpxio.h"
58 #include "viewit.h"
59 #include "mtop_util.h"
60 #include "gmx_ana.h"
63 static real minthird=-1.0/3.0,minsixth=-1.0/6.0;
65 typedef struct {
66 real sum;
67 real sum2;
68 } exactsum_t;
70 typedef struct {
71 real *ener;
72 exactsum_t *es;
73 bool bExactStat;
74 double av;
75 double rmsd;
76 double ee;
77 double slope;
78 } enerdat_t;
80 typedef struct {
81 gmx_large_int_t nsteps;
82 gmx_large_int_t npoints;
83 int nframes;
84 int *step;
85 int *steps;
86 int *points;
87 enerdat_t *s;
88 } enerdata_t;
90 static double mypow(double x,double y)
92 if (x > 0)
93 return pow(x,y);
94 else
95 return 0.0;
98 static int *select_it(int nre,char *nm[],int *nset)
100 bool *bE;
101 int n,k,j,i;
102 int *set;
103 bool bVerbose = TRUE;
105 if ((getenv("VERBOSE")) != NULL)
106 bVerbose = FALSE;
108 fprintf(stderr,"Select the terms you want from the following list\n");
109 fprintf(stderr,"End your selection with 0\n");
111 if ( bVerbose ) {
112 for(k=0; (k<nre); ) {
113 for(j=0; (j<4) && (k<nre); j++,k++)
114 fprintf(stderr," %3d=%14s",k+1,nm[k]);
115 fprintf(stderr,"\n");
119 snew(bE,nre);
120 do {
121 if(1 != scanf("%d",&n))
123 gmx_fatal(FARGS,"Error reading user input");
125 if ((n>0) && (n<=nre))
126 bE[n-1]=TRUE;
127 } while (n != 0);
129 snew(set,nre);
130 for(i=(*nset)=0; (i<nre); i++)
131 if (bE[i])
132 set[(*nset)++]=i;
134 sfree(bE);
136 return set;
139 static int strcount(const char *s1,const char *s2)
141 int n=0;
142 while (s1 && s2 && (toupper(s1[n]) == toupper(s2[n])))
143 n++;
144 return n;
147 static void chomp(char *buf)
149 int len = strlen(buf);
151 while ((len > 0) && (buf[len-1] == '\n')) {
152 buf[len-1] = '\0';
153 len--;
157 static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
159 bool *bE;
160 int n,k,kk,j,i,nmatch,nind,nss;
161 int *set;
162 bool bEOF,bVerbose = TRUE,bLong=FALSE;
163 char *ptr,buf[STRLEN];
164 const char *fm4="%3d %-14s";
165 const char *fm2="%3d %-34s";
166 char **newnm=NULL;
168 if ((getenv("VERBOSE")) != NULL)
169 bVerbose = FALSE;
171 fprintf(stderr,"\n");
172 fprintf(stderr,"Select the terms you want from the following list by\n");
173 fprintf(stderr,"selecting either (part of) the name or the number or a combination.\n");
174 fprintf(stderr,"End your selection with an empty line or a zero.\n");
175 fprintf(stderr,"-------------------------------------------------------------------\n");
177 snew(newnm,nre);
178 j = 0;
179 for(k=0; k<nre; k++) {
180 newnm[k] = strdup(nm[k].name);
181 /* Insert dashes in all the names */
182 while ((ptr = strchr(newnm[k],' ')) != NULL) {
183 *ptr = '-';
185 if ( bVerbose ) {
186 if (j == 0) {
187 if (k > 0) {
188 fprintf(stderr,"\n");
190 bLong = FALSE;
191 for(kk=k; kk<k+4; kk++) {
192 if (kk < nre && strlen(nm[kk].name) > 14) {
193 bLong = TRUE;
196 } else {
197 fprintf(stderr," ");
199 if (!bLong) {
200 fprintf(stderr,fm4,k+1,newnm[k]);
201 j++;
202 if (j == 4) {
203 j = 0;
205 } else {
206 fprintf(stderr,fm2,k+1,newnm[k]);
207 j++;
208 if (j == 2) {
209 j = 0;
214 if ( bVerbose ) {
215 fprintf(stderr,"\n\n");
218 snew(bE,nre);
220 bEOF = FALSE;
221 while (!bEOF && (fgets2(buf,STRLEN-1,stdin))) {
222 /* Remove newlines */
223 chomp(buf);
225 /* Remove spaces */
226 trim(buf);
228 /* Empty line means end of input */
229 bEOF = (strlen(buf) == 0);
230 if (!bEOF) {
231 ptr = buf;
232 do {
233 if (!bEOF) {
234 /* First try to read an integer */
235 nss = sscanf(ptr,"%d",&nind);
236 if (nss == 1) {
237 /* Zero means end of input */
238 if (nind == 0) {
239 bEOF = TRUE;
240 } else if ((1<=nind) && (nind<=nre)) {
241 bE[nind-1] = TRUE;
242 } else {
243 fprintf(stderr,"number %d is out of range\n",nind);
246 else {
247 /* Now try to read a string */
248 i = strlen(ptr);
249 nmatch = 0;
250 for(nind=0; nind<nre; nind++) {
251 if (strcasecmp(newnm[nind],ptr) == 0) {
252 bE[nind] = TRUE;
253 nmatch++;
256 if (nmatch == 0) {
257 i = strlen(ptr);
258 nmatch = 0;
259 for(nind=0; nind<nre; nind++) {
260 if (strncasecmp(newnm[nind],ptr,i) == 0) {
261 bE[nind] = TRUE;
262 nmatch++;
265 if (nmatch == 0) {
266 fprintf(stderr,"String '%s' does not match anything\n",ptr);
271 /* Look for the first space, and remove spaces from there */
272 if ((ptr = strchr(ptr,' ')) != NULL) {
273 trim(ptr);
275 } while (!bEOF && (ptr && (strlen(ptr) > 0)));
279 snew(set,nre);
280 for(i=(*nset)=0; (i<nre); i++)
281 if (bE[i])
282 set[(*nset)++]=i;
284 sfree(bE);
286 if (*nset == 0)
287 gmx_fatal(FARGS,"No energy terms selected");
289 for(i=0; (i<nre); i++)
290 sfree(newnm[i]);
291 sfree(newnm);
293 return set;
296 static void get_orires_parms(const char *topnm,
297 int *nor,int *nex,int **label,real **obs)
299 gmx_mtop_t mtop;
300 gmx_localtop_t *top;
301 t_inputrec ir;
302 t_iparams *ip;
303 int natoms,i;
304 t_iatom *iatom;
305 int nb;
306 matrix box;
308 read_tpx(topnm,&ir,box,&natoms,NULL,NULL,NULL,&mtop);
309 top = gmx_mtop_generate_local_top(&mtop,&ir);
311 ip = top->idef.iparams;
312 iatom = top->idef.il[F_ORIRES].iatoms;
314 /* Count how many distance restraint there are... */
315 nb = top->idef.il[F_ORIRES].nr;
316 if (nb == 0)
317 gmx_fatal(FARGS,"No orientation restraints in topology!\n");
319 *nor = nb/3;
320 *nex = 0;
321 snew(*label,*nor);
322 snew(*obs,*nor);
323 for(i=0; i<nb; i+=3) {
324 (*label)[i/3] = ip[iatom[i]].orires.label;
325 (*obs)[i/3] = ip[iatom[i]].orires.obs;
326 if (ip[iatom[i]].orires.ex >= *nex)
327 *nex = ip[iatom[i]].orires.ex+1;
329 fprintf(stderr,"Found %d orientation restraints with %d experiments",
330 *nor,*nex);
333 static int get_bounds(const char *topnm,
334 real **bounds,int **index,int **dr_pair,int *npairs,
335 gmx_mtop_t *mtop,gmx_localtop_t **ltop,t_inputrec *ir)
337 gmx_localtop_t *top;
338 t_functype *functype;
339 t_iparams *ip;
340 int natoms,i,j,k,type,ftype,natom;
341 t_ilist *disres;
342 t_iatom *iatom;
343 real *b;
344 int *ind,*pair;
345 int nb,label1;
346 matrix box;
348 read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,mtop);
349 snew(*ltop,1);
350 top = gmx_mtop_generate_local_top(mtop,ir);
351 *ltop = top;
353 functype = top->idef.functype;
354 ip = top->idef.iparams;
356 /* Count how many distance restraint there are... */
357 nb=top->idef.il[F_DISRES].nr;
358 if (nb == 0)
359 gmx_fatal(FARGS,"No distance restraints in topology!\n");
361 /* Allocate memory */
362 snew(b,nb);
363 snew(ind,nb);
364 snew(pair,nb+1);
366 /* Fill the bound array */
367 nb=0;
368 for(i=0; (i<top->idef.ntypes); i++) {
369 ftype = functype[i];
370 if (ftype == F_DISRES) {
372 label1 = ip[i].disres.label;
373 b[nb] = ip[i].disres.up1;
374 ind[nb] = label1;
375 nb++;
378 *bounds = b;
380 /* Fill the index array */
381 label1 = -1;
382 disres = &(top->idef.il[F_DISRES]);
383 iatom = disres->iatoms;
384 for(i=j=k=0; (i<disres->nr); ) {
385 type = iatom[i];
386 ftype = top->idef.functype[type];
387 natom = interaction_function[ftype].nratoms+1;
388 if (label1 != top->idef.iparams[type].disres.label) {
389 pair[j] = k;
390 label1 = top->idef.iparams[type].disres.label;
391 j ++;
393 k++;
394 i += natom;
396 pair[j] = k;
397 *npairs = k;
398 if (j != nb)
399 gmx_incons("get_bounds for distance restraints");
401 *index = ind;
402 *dr_pair = pair;
404 return nb;
407 static void calc_violations(real rt[],real rav3[],int nb,int index[],
408 real bounds[],real *viol,double *st,double *sa)
410 const real sixth=1.0/6.0;
411 int i,j;
412 double rsum,rav,sumaver,sumt;
414 sumaver = 0;
415 sumt = 0;
416 for(i=0; (i<nb); i++) {
417 rsum = 0.0;
418 rav = 0.0;
419 for(j=index[i]; (j<index[i+1]); j++) {
420 if (viol)
421 viol[j] += mypow(rt[j],-3.0);
422 rav += sqr(rav3[j]);
423 rsum += mypow(rt[j],-6);
425 rsum = max(0.0,mypow(rsum,-sixth)-bounds[i]);
426 rav = max(0.0,mypow(rav, -sixth)-bounds[i]);
428 sumt += rsum;
429 sumaver += rav;
431 *st = sumt;
432 *sa = sumaver;
435 static void analyse_disre(const char *voutfn, int nframes,
436 real violaver[], real bounds[], int index[],
437 int pair[], int nbounds,
438 const output_env_t oenv)
440 FILE *vout;
441 double sum,sumt,sumaver;
442 int i,j;
444 /* Subtract bounds from distances, to calculate violations */
445 calc_violations(violaver,violaver,
446 nbounds,pair,bounds,NULL,&sumt,&sumaver);
448 #ifdef DEBUG
449 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
450 sumaver);
451 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",
452 sumt);
453 #endif
454 vout=xvgropen(voutfn,"r\\S-3\\N average violations","DR Index","nm",
455 oenv);
456 sum = 0.0;
457 sumt = 0.0;
458 for(i=0; (i<nbounds); i++) {
459 /* Do ensemble averaging */
460 sumaver = 0;
461 for(j=pair[i]; (j<pair[i+1]); j++)
462 sumaver += sqr(violaver[j]/nframes);
463 sumaver = max(0.0,mypow(sumaver,minsixth)-bounds[i]);
465 sumt += sumaver;
466 sum = max(sum,sumaver);
467 fprintf(vout,"%10d %10.5e\n",index[i],sumaver);
469 #ifdef DEBUG
470 for(j=0; (j<dr.ndr); j++)
471 fprintf(vout,"%10d %10.5e\n",j,mypow(violaver[j]/nframes,minthird));
472 #endif
473 ffclose(vout);
475 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
476 sumt);
477 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",sum);
479 do_view(oenv,voutfn,"-graphtype bar");
482 static void einstein_visco(const char *fn,const char *fni,int nsets,
483 int nframes,real **sum,
484 real V,real T,int nsteps,double time[],
485 const output_env_t oenv)
487 FILE *fp0,*fp1;
488 double av[4],avold[4];
489 double fac,dt,di;
490 int i,j,m,nf4;
492 if (nframes < 1)
493 return;
495 dt = (time[1]-time[0]);
496 nf4 = nframes/4+1;
498 for(i=0; i<=nsets; i++)
499 avold[i] = 0;
500 fp0=xvgropen(fni,"Shear viscosity integral",
501 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N ps)",oenv);
502 fp1=xvgropen(fn,"Shear viscosity using Einstein relation",
503 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N)",oenv);
504 for(i=1; i<nf4; i++) {
505 fac = dt*nframes/nsteps;
506 for(m=0; m<=nsets; m++)
507 av[m] = 0;
508 for(j=0; j<nframes-i; j++) {
509 for(m=0; m<nsets; m++) {
510 di = sqr(fac*(sum[m][j+i]-sum[m][j]));
512 av[m] += di;
513 av[nsets] += di/nsets;
516 /* Convert to SI for the viscosity */
517 fac = (V*NANO*NANO*NANO*PICO*1e10)/(2*BOLTZMANN*T)/(nframes-i);
518 fprintf(fp0,"%10g",time[i]-time[0]);
519 for(m=0; (m<=nsets); m++) {
520 av[m] = fac*av[m];
521 fprintf(fp0," %10g",av[m]);
523 fprintf(fp0,"\n");
524 fprintf(fp1,"%10g",0.5*(time[i]+time[i-1])-time[0]);
525 for(m=0; (m<=nsets); m++) {
526 fprintf(fp1," %10g",(av[m]-avold[m])/dt);
527 avold[m] = av[m];
529 fprintf(fp1,"\n");
531 ffclose(fp0);
532 ffclose(fp1);
535 typedef struct {
536 gmx_large_int_t np;
537 double sum;
538 double sav;
539 double sav2;
540 } ee_sum_t;
542 typedef struct {
543 int b;
544 ee_sum_t sum;
545 gmx_large_int_t nst;
546 gmx_large_int_t nst_min;
547 } ener_ee_t;
549 static void clear_ee_sum(ee_sum_t *ees)
551 ees->sav = 0;
552 ees->sav2 = 0;
553 ees->np = 0;
554 ees->sum = 0;
557 static void add_ee_sum(ee_sum_t *ees,double sum,int np)
559 ees->np += np;
560 ees->sum += sum;
563 static void add_ee_av(ee_sum_t *ees)
565 double av;
567 av = ees->sum/ees->np;
568 ees->sav += av;
569 ees->sav2 += av*av;
570 ees->np = 0;
571 ees->sum = 0;
574 static double calc_ee2(int nb,ee_sum_t *ees)
576 return (ees->sav2/nb - dsqr(ees->sav/nb))/(nb - 1);
579 static void set_ee_av(ener_ee_t *eee)
581 if (debug)
583 char buf[STEPSTRSIZE];
584 fprintf(debug,"Storing average for err.est.: %s steps\n",
585 gmx_step_str(eee->nst,buf));
587 add_ee_av(&eee->sum);
588 eee->b++;
589 if (eee->b == 1 || eee->nst < eee->nst_min)
591 eee->nst_min = eee->nst;
593 eee->nst = 0;
596 static void calc_averages(int nset,enerdata_t *edat,int nbmin,int nbmax)
598 int nb,i,f,nee;
599 double sum,sum2,sump,see2;
600 gmx_large_int_t steps,np,p,bound_nb;
601 enerdat_t *ed;
602 exactsum_t *es;
603 bool bAllZero;
604 double x,sx,sy,sxx,sxy;
605 ener_ee_t *eee;
607 /* Check if we have exact statistics over all points */
608 for(i=0; i<nset; i++)
610 ed = &edat->s[i];
611 ed->bExactStat = FALSE;
612 if (edat->npoints > 0)
614 /* All energy file sum entries 0 signals no exact sums.
615 * But if all energy values are 0, we still have exact sums.
617 bAllZero = TRUE;
618 for(f=0; f<edat->nframes && !ed->bExactStat; f++)
620 if (ed->ener[i] != 0)
622 bAllZero = FALSE;
624 ed->bExactStat = (ed->es[f].sum != 0);
626 if (bAllZero)
628 ed->bExactStat = TRUE;
633 snew(eee,nbmax+1);
634 for(i=0; i<nset; i++)
636 ed = &edat->s[i];
638 sum = 0;
639 sum2 = 0;
640 np = 0;
641 sx = 0;
642 sy = 0;
643 sxx = 0;
644 sxy = 0;
645 for(nb=nbmin; nb<=nbmax; nb++)
647 eee[nb].b = 0;
648 clear_ee_sum(&eee[nb].sum);
649 eee[nb].nst = 0;
650 eee[nb].nst_min = 0;
652 for(f=0; f<edat->nframes; f++)
654 es = &ed->es[f];
656 if (ed->bExactStat)
658 /* Add the sum and the sum of variances to the totals. */
659 p = edat->points[f];
660 sump = es->sum;
661 sum2 += es->sum2;
662 if (np > 0)
664 sum2 += dsqr(sum/np - (sum + es->sum)/(np + p))
665 *np*(np + p)/p;
668 else
670 /* Add a single value to the sum and sum of squares. */
671 p = 1;
672 sump = ed->ener[f];
673 sum2 += dsqr(sump);
676 /* sum has to be increased after sum2 */
677 np += p;
678 sum += sump;
680 /* For the linear regression use variance 1/p.
681 * Note that sump is the sum, not the average, so we don't need p*.
683 x = edat->step[f] - 0.5*(edat->steps[f] - 1);
684 sx += p*x;
685 sy += sump;
686 sxx += p*x*x;
687 sxy += x*sump;
689 for(nb=nbmin; nb<=nbmax; nb++)
691 /* Check if the current end step is closer to the desired
692 * block boundary than the next end step.
694 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
695 if (eee[nb].nst > 0 &&
696 bound_nb - edat->step[f-1]*nb < edat->step[f]*nb - bound_nb)
698 set_ee_av(&eee[nb]);
700 if (f == 0)
702 eee[nb].nst = 1;
704 else
706 eee[nb].nst += edat->step[f] - edat->step[f-1];
708 if (ed->bExactStat)
710 add_ee_sum(&eee[nb].sum,es->sum,edat->points[f]);
712 else
714 add_ee_sum(&eee[nb].sum,edat->s[i].ener[f],1);
716 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
717 if (edat->step[f]*nb >= bound_nb)
719 set_ee_av(&eee[nb]);
724 edat->s[i].av = sum/np;
725 if (ed->bExactStat)
727 edat->s[i].rmsd = sqrt(sum2/np);
729 else
731 edat->s[i].rmsd = sqrt(sum2/np - dsqr(edat->s[i].av));
734 if (edat->nframes > 1)
736 edat->s[i].slope = (np*sxy - sx*sy)/(np*sxx - sx*sx);
738 else
740 edat->s[i].slope = 0;
743 nee = 0;
744 see2 = 0;
745 for(nb=nbmin; nb<=nbmax; nb++)
747 /* Check if we actually got nb blocks and if the smallest
748 * block is not shorter than 80% of the average.
750 if (debug)
752 char buf1[STEPSTRSIZE],buf2[STEPSTRSIZE];
753 fprintf(debug,"Requested %d blocks, we have %d blocks, min %s nsteps %s\n",
754 nb,eee[nb].b,
755 gmx_step_str(eee[nb].nst_min,buf1),
756 gmx_step_str(edat->nsteps,buf2));
758 if (eee[nb].b == nb && 5*nb*eee[nb].nst_min >= 4*edat->nsteps)
760 see2 += calc_ee2(nb,&eee[nb].sum);
761 nee++;
764 if (nee > 0)
766 edat->s[i].ee = sqrt(see2/nee);
768 else
770 edat->s[i].ee = -1;
773 sfree(eee);
776 static enerdata_t *calc_sum(int nset,enerdata_t *edat,int nbmin,int nbmax)
778 enerdata_t *esum;
779 enerdat_t *s;
780 int f,i;
781 double sum;
783 snew(esum,1);
784 *esum = *edat;
785 snew(esum->s,1);
786 s = &esum->s[0];
787 snew(s->ener,esum->nframes);
788 snew(s->es ,esum->nframes);
790 s->bExactStat = TRUE;
791 s->slope = 0;
792 for(i=0; i<nset; i++)
794 if (!edat->s[i].bExactStat)
796 s->bExactStat = FALSE;
798 s->slope += edat->s[i].slope;
801 for(f=0; f<edat->nframes; f++)
803 sum = 0;
804 for(i=0; i<nset; i++)
806 sum += edat->s[i].ener[f];
808 s->ener[f] = sum;
809 sum = 0;
810 for(i=0; i<nset; i++)
812 sum += edat->s[i].es[f].sum;
814 s->es[f].sum = sum;
815 s->es[f].sum2 = 0;
818 calc_averages(1,esum,nbmin,nbmax);
820 return esum;
823 static char *ee_pr(double ee,char *buf)
825 char tmp[100];
826 double rnd;
828 if (ee < 0)
830 sprintf(buf,"%s","--");
832 else
834 /* Round to two decimals by printing. */
835 sprintf(tmp,"%.1e",ee);
836 sscanf(tmp,"%lf",&rnd);
837 sprintf(buf,"%g",rnd);
840 return buf;
843 static void analyse_ener(bool bCorr,const char *corrfn,
844 bool bFee,bool bSum,bool bFluct,bool bTempFluct,
845 bool bVisco,const char *visfn,int nmol,
846 int nconstr,
847 gmx_large_int_t start_step,double start_t,
848 gmx_large_int_t step,double t,
849 double time[], real reftemp,
850 enerdata_t *edat,
851 int nset,int set[],bool *bIsEner,
852 char **leg,gmx_enxnm_t *enm,
853 real Vaver,real ezero,
854 int nbmin,int nbmax,
855 const output_env_t oenv)
857 FILE *fp;
858 /* Check out the printed manual for equations! */
859 double Dt,aver,stddev,errest,delta_t,totaldrift;
860 enerdata_t *esum=NULL;
861 real xxx,integral,intBulk;
862 real sfrac,oldfrac,diffsum,diffav,fstep,pr_aver,pr_stddev,pr_errest;
863 double beta=0,expE,expEtot,*fee=NULL;
864 gmx_large_int_t nsteps;
865 int nexact,nnotexact;
866 double x1m,x1mk;
867 real Temp=-1,Pres=-1,VarV=-1,VarT=-1,VarEtot=-1,AvEtot=0,VarEnthalpy=-1;
868 int i,j,nout;
869 real chi2;
870 char buf[256],eebuf[100];
872 nsteps = step - start_step + 1;
873 if (nsteps < 1) {
874 fprintf(stdout,"Not enough steps (%s) for statistics\n",
875 gmx_step_str(nsteps,buf));
877 else {
878 /* Calculate the time difference */
879 delta_t = t - start_t;
881 fprintf(stdout,"\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
882 gmx_step_str(nsteps,buf),start_t,t,nset);
884 calc_averages(nset,edat,nbmin,nbmax);
886 if (bSum) {
887 esum = calc_sum(nset,edat,nbmin,nbmax);
890 if (edat->npoints == 0) {
891 nexact = 0;
892 nnotexact = nset;
893 } else {
894 nexact = 0;
895 nnotexact = 0;
896 for(i=0; (i<nset); i++) {
897 if (edat->s[i].bExactStat) {
898 nexact++;
899 } else {
900 nnotexact++;
905 if (nnotexact == 0) {
906 fprintf(stdout,"All statistics are over %s points\n",
907 gmx_step_str(edat->npoints,buf));
908 } else if (nexact == 0 || edat->npoints == edat->nframes) {
909 fprintf(stdout,"All statistics are over %d points (frames)\n",
910 edat->nframes);
911 } else {
912 fprintf(stdout,"The term%s",nnotexact==1 ? "" : "s");
913 for(i=0; (i<nset); i++) {
914 if (!edat->s[i].bExactStat) {
915 fprintf(stdout," '%s'",leg[i]);
918 fprintf(stdout," %s has statistics over %d points (frames)\n",
919 nnotexact==1 ? "is" : "are",edat->nframes);
920 fprintf(stdout,"All other statistics are over %s points\n",
921 gmx_step_str(edat->npoints,buf));
923 fprintf(stdout,"\n");
925 fprintf(stdout,"%-24s %10s %10s %10s %10s",
926 "Energy","Average","Err.Est.","RMSD","Tot-Drift");
927 if (bFee)
928 fprintf(stdout," %10s\n","-kT ln<e^(E/kT)>");
929 else
930 fprintf(stdout,"\n");
931 fprintf(stdout,"-------------------------------------------------------------------------------\n");
933 /* Initiate locals, only used with -sum */
934 expEtot=0;
935 if (bFee) {
936 beta = 1.0/(BOLTZ*reftemp);
937 snew(fee,nset);
939 for(i=0; (i<nset); i++) {
940 aver = edat->s[i].av;
941 stddev = edat->s[i].rmsd;
942 errest = edat->s[i].ee;
944 if (bFee) {
945 expE = 0;
946 for(j=0; (j<edat->nframes); j++) {
947 expE += exp(beta*(edat->s[i].ener[j] - aver)/nmol);
949 if (bSum)
950 expEtot+=expE/edat->nframes;
952 fee[i] = log(expE/edat->nframes)/beta + aver/nmol;
954 if (strstr(leg[i],"empera") != NULL) {
955 VarT = sqr(stddev);
956 Temp = aver;
957 } else if (strstr(leg[i],"olum") != NULL) {
958 VarV = sqr(stddev);
959 Vaver= aver;
960 } else if (strstr(leg[i],"essure") != NULL) {
961 Pres = aver;
962 } else if (strstr(leg[i],"otal") != NULL) {
963 VarEtot = sqr(stddev);
964 AvEtot = aver;
965 } else if (strstr(leg[i],"nthalpy") != NULL) {
966 VarEnthalpy = sqr(stddev);
968 if (bIsEner[i]) {
969 pr_aver = aver/nmol-ezero;
970 pr_stddev = stddev/nmol;
971 pr_errest = errest/nmol;
973 else {
974 pr_aver = aver;
975 pr_stddev = stddev;
976 pr_errest = errest;
979 /* Multiply the slope in steps with the number of steps taken */
980 totaldrift = (edat->nsteps - 1)*edat->s[i].slope;
981 if (bIsEner[i])
983 totaldrift /= nmol;
986 fprintf(stdout,"%-24s %10g %10s %10g %10g",
987 leg[i],pr_aver,ee_pr(pr_errest,eebuf),pr_stddev,totaldrift);
988 if (bFee)
989 fprintf(stdout," %10g",fee[i]);
991 fprintf(stdout," (%s)\n",enm[set[i]].unit);
993 if (bFluct) {
994 for(j=0; (j<edat->nframes); j++)
995 edat->s[i].ener[j] -= aver;
998 if (bSum) {
999 totaldrift = (edat->nsteps - 1)*esum->s[0].slope;
1000 fprintf(stdout,"%-24s %10g %10s %10s %10g (%s)",
1001 "Total",esum->s[0].av/nmol,ee_pr(esum->s[0].ee/nmol,eebuf),
1002 "--",totaldrift/nmol,enm[set[0]].unit);
1003 /* pr_aver,pr_stddev,a,totaldrift */
1004 if (bFee)
1005 fprintf(stdout," %10g %10g\n",
1006 log(expEtot)/beta + esum->s[0].av/nmol,log(expEtot)/beta);
1007 else
1008 fprintf(stdout,"\n");
1010 if (bTempFluct && Temp != -1) {
1011 printf("\nTemperature dependent fluctuation properties at T = %g. #constr/mol = %d\n",Temp,nconstr);
1012 if (nmol < 2)
1013 printf("Warning: nmol = %d, this may not be what you want.\n",
1014 nmol);
1015 if (VarV != -1) {
1016 real tmp = VarV/(Vaver*BOLTZ*Temp*PRESFAC);
1018 printf("Isothermal Compressibility: %10g /%s\n",
1019 tmp,unit_pres_bar);
1020 printf("Adiabatic bulk modulus: %10g %s\n",
1021 1.0/tmp,unit_pres_bar);
1023 if (VarEnthalpy != -1) {
1024 real Cp = 1000*((VarEnthalpy/nmol)/(BOLTZ*Temp*Temp) -
1025 0.5*BOLTZ*nconstr);
1026 printf("Heat capacity at constant pressure Cp: %10g J/mol K\n",Cp);
1028 if ((VarV != -1) && (VarEnthalpy != -1)) {
1029 real aP = (sqrt(VarEnthalpy*VarV/nmol))/(BOLTZ*Vaver*Temp*Temp);
1030 printf("Thermal expansion coefficient alphaP: %10g 1/K\n",aP);
1032 if ((VarV == -1) && (VarEtot != -1)) {
1033 real Cv = 1000*((VarEtot/nmol)/(BOLTZ*Temp*Temp) -
1034 0.5*BOLTZ*nconstr);
1035 printf("Heat capacity at constant volume Cv: %10g J/mol K\n",Cv);
1037 please_cite(stdout,"Allen1987a");
1039 /* Do correlation function */
1040 if (edat->nframes > 1)
1042 Dt = delta_t/(edat->nframes - 1);
1044 else
1046 Dt = 0;
1048 if (bVisco) {
1049 char *leg[] = { "Shear", "Bulk" };
1050 real factor;
1051 real **eneset;
1052 real **enesum;
1054 /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
1056 /* Symmetrise tensor! (and store in first three elements)
1057 * And subtract average pressure!
1059 snew(eneset,12);
1060 for(i=0; i<12; i++) {
1061 snew(eneset[i],edat->nframes);
1063 snew(enesum,3);
1064 for(i=0; i<3; i++) {
1065 snew(enesum[i],edat->nframes);
1067 for(i=0; (i<edat->nframes); i++) {
1068 eneset[0][i] = 0.5*(edat->s[1].ener[i]+edat->s[3].ener[i]);
1069 eneset[1][i] = 0.5*(edat->s[2].ener[i]+edat->s[6].ener[i]);
1070 eneset[2][i] = 0.5*(edat->s[5].ener[i]+edat->s[7].ener[i]);
1071 for(j=3; j<=11; j++) {
1072 eneset[j][i] = edat->s[j].ener[i];
1074 eneset[11][i] -= Pres;
1075 enesum[0][i] = 0.5*(edat->s[1].es[i].sum+edat->s[3].es[i].sum);
1076 enesum[1][i] = 0.5*(edat->s[2].es[i].sum+edat->s[6].es[i].sum);
1077 enesum[2][i] = 0.5*(edat->s[5].es[i].sum+edat->s[7].es[i].sum);
1080 einstein_visco("evisco.xvg","eviscoi.xvg",
1081 3,edat->nframes,enesum,Vaver,Temp,nsteps,time,oenv);
1083 /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
1084 /* Do it for shear viscosity */
1085 strcpy(buf,"Shear Viscosity");
1086 low_do_autocorr(corrfn,oenv,buf,edat->nframes,3,
1087 (edat->nframes+1)/2,eneset,Dt,
1088 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1090 /* Now for bulk viscosity */
1091 strcpy(buf,"Bulk Viscosity");
1092 low_do_autocorr(corrfn,oenv,buf,edat->nframes,1,
1093 (edat->nframes+1)/2,&(eneset[11]),Dt,
1094 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1096 factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
1097 fp=xvgropen(visfn,buf,"Time (ps)","\\8h\\4 (cp)",oenv);
1098 xvgr_legend(fp,asize(leg),leg,oenv);
1100 /* Use trapezium rule for integration */
1101 integral = 0;
1102 intBulk = 0;
1103 nout = get_acfnout();
1104 if ((nout < 2) || (nout >= edat->nframes/2))
1105 nout = edat->nframes/2;
1106 for(i=1; (i<nout); i++)
1108 integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
1109 intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
1110 fprintf(fp,"%10g %10g %10g\n",(i*Dt),integral,intBulk);
1112 ffclose(fp);
1114 else if (bCorr) {
1115 if (bFluct)
1116 strcpy(buf,"Autocorrelation of Energy Fluctuations");
1117 else
1118 strcpy(buf,"Energy Autocorrelation");
1119 #if 0
1120 do_autocorr(corrfn,oenv,buf,edat->nframes,
1121 bSum ? 1 : nset,
1122 bSum ? &edat->s[nset-1].ener : eneset,
1123 (delta_t/edat->nframes),eacNormal,FALSE);
1124 #endif
1129 static void print_time(FILE *fp,double t)
1131 fprintf(fp,"%12.6f",t);
1134 static void print1(FILE *fp,bool bDp,real e)
1136 if (bDp)
1137 fprintf(fp," %16.12f",e);
1138 else
1139 fprintf(fp," %10.6f",e);
1142 static void fec(const char *ene2fn, const char *runavgfn,
1143 real reftemp, int nset, int set[], char *leg[],
1144 enerdata_t *edat, double time[],
1145 const output_env_t oenv)
1147 char *ravgleg[] = { "\\8D\\4E = E\\sB\\N-E\\sA\\N",
1148 "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N" };
1149 FILE *fp;
1150 ener_file_t enx;
1151 int nre,timecheck,step,nenergy,nenergy2,maxenergy;
1152 int i,j;
1153 bool bCont;
1154 real aver, beta;
1155 real **eneset2;
1156 double dE, sum;
1157 gmx_enxnm_t *enm=NULL;
1158 t_enxframe *fr;
1159 char buf[22];
1161 /* read second energy file */
1162 snew(fr,1);
1163 enm = NULL;
1164 enx = open_enx(ene2fn,"r");
1165 do_enxnms(enx,&(fr->nre),&enm);
1167 snew(eneset2,nset+1);
1168 nenergy2=0;
1169 maxenergy=0;
1170 timecheck=0;
1171 do {
1172 /* This loop searches for the first frame (when -b option is given),
1173 * or when this has been found it reads just one energy frame
1175 do {
1176 bCont = do_enx(enx,fr);
1178 if (bCont)
1179 timecheck = check_times(fr->t);
1181 } while (bCont && (timecheck < 0));
1183 /* Store energies for analysis afterwards... */
1184 if ((timecheck == 0) && bCont) {
1185 if (fr->nre > 0) {
1186 if ( nenergy2 >= maxenergy ) {
1187 maxenergy += 1000;
1188 for(i=0; i<=nset; i++)
1189 srenew(eneset2[i],maxenergy);
1191 if (fr->t != time[nenergy2])
1192 fprintf(stderr,"\nWARNING time mismatch %g!=%g at frame %s\n",
1193 fr->t, time[nenergy2], gmx_step_str(fr->step,buf));
1194 for(i=0; i<nset; i++)
1195 eneset2[i][nenergy2] = fr->ener[set[i]].e;
1196 nenergy2++;
1199 } while (bCont && (timecheck == 0));
1201 /* check */
1202 if (edat->nframes != nenergy2) {
1203 fprintf(stderr,"\nWARNING file length mismatch %d!=%d\n",
1204 edat->nframes,nenergy2);
1206 nenergy = min(edat->nframes,nenergy2);
1208 /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
1209 fp=NULL;
1210 if (runavgfn) {
1211 fp=xvgropen(runavgfn,"Running average free energy difference",
1212 "Time (" unit_time ")","\\8D\\4E (" unit_energy ")",oenv);
1213 xvgr_legend(fp,asize(ravgleg),ravgleg,oenv);
1215 fprintf(stdout,"\n%-24s %10s\n",
1216 "Energy","dF = -kT ln < exp(-(EB-EA)/kT) >A");
1217 sum=0;
1218 beta = 1.0/(BOLTZ*reftemp);
1219 for(i=0; i<nset; i++) {
1220 if (strcasecmp(leg[i],enm[set[i]].name)!=0)
1221 fprintf(stderr,"\nWARNING energy set name mismatch %s!=%s\n",
1222 leg[i],enm[set[i]].name);
1223 for(j=0; j<nenergy; j++) {
1224 dE = eneset2[i][j] - edat->s[i].ener[j];
1225 sum += exp(-dE*beta);
1226 if (fp)
1227 fprintf(fp,"%10g %10g %10g\n",
1228 time[j], dE, -BOLTZ*reftemp*log(sum/(j+1)) );
1230 aver = -BOLTZ*reftemp*log(sum/nenergy);
1231 fprintf(stdout,"%-24s %10g\n",leg[i],aver);
1233 if(fp) ffclose(fp);
1234 sfree(fr);
1237 int gmx_energy(int argc,char *argv[])
1239 const char *desc[] = {
1241 "g_energy extracts energy components or distance restraint",
1242 "data from an energy file. The user is prompted to interactively",
1243 "select the energy terms she wants.[PAR]",
1245 "Average, RMSD and drift are calculated with full precision from the",
1246 "simulation (see printed manual). Drift is calculated by performing",
1247 "a LSQ fit of the data to a straight line. The reported total drift",
1248 "is the difference of the fit at the first and last point.",
1249 "An error estimate of the average is given based on a block averages",
1250 "over 5 blocks using the full precision averages. The error estimate",
1251 "can be performed over multiple block lengths with the options",
1252 "[TT]-nbmin[tt] and [TT]-nbmax[tt].",
1253 "Note that in most cases the energy files contains averages over all",
1254 "MD steps, or over many more points than the number of frames in",
1255 "energy file. This makes the g_energy statistics output more accurate",
1256 "than the xvg output. When exact averages are not present in the energy",
1257 "file the statistics mentioned above is simply over the single, per-frame",
1258 "energy values.[PAR]",
1260 "The term fluctuation gives the RMSD around the LSQ fit.[PAR]",
1262 "Some fluctuation-dependent properties can be calculated provided",
1263 "the correct energy terms are selected. The following properties",
1264 "will be computed:[BR]",
1265 "Property Energy terms needed[BR]",
1266 "--------------------------------------------------[BR]",
1267 "Heat capacity Cp (NPT sims) Enthalpy, Temp [BR]",
1268 "Heat capacity Cv (NVT sims) Etot, Temp [BR]",
1269 "Thermal expansion coeff. (NPT) Enthalpy, Vol, Temp[BR]",
1270 "Isothermal compressibility Vol, Temp [BR]",
1271 "Adiabatic bulk modulus Vol, Temp [PBR]",
1272 "--------------------------------------------------[BR]",
1273 "You always need to set the number of molecules [TT]-nmol[tt], and,",
1274 "if you used constraints in your simulations you will need to give",
1275 "the number of constraints per molecule [TT]-nconstr[tt] in order to",
1276 "correct for this: (nconstr/2) kB is subtracted from the heat",
1277 "capacity in this case. For instance in the case of rigid water",
1278 "you need to give the value 3 to this option.[PAR]",
1280 "When the [TT]-viol[tt] option is set, the time averaged",
1281 "violations are plotted and the running time-averaged and",
1282 "instantaneous sum of violations are recalculated. Additionally",
1283 "running time-averaged and instantaneous distances between",
1284 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
1286 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
1287 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
1288 "The first two options plot the orientation, the last three the",
1289 "deviations of the orientations from the experimental values.",
1290 "The options that end on an 'a' plot the average over time",
1291 "as a function of restraint. The options that end on a 't'",
1292 "prompt the user for restraint label numbers and plot the data",
1293 "as a function of time. Option [TT]-odr[tt] plots the RMS",
1294 "deviation as a function of restraint.",
1295 "When the run used time or ensemble averaged orientation restraints,",
1296 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
1297 "not ensemble-averaged orientations and deviations instead of",
1298 "the time and ensemble averages.[PAR]",
1300 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
1301 "tensor for each orientation restraint experiment. With option",
1302 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
1304 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
1305 "difference with an ideal gas state: [BR]",
1306 " Delta A = A(N,V,T) - A_idgas(N,V,T) = kT ln < e^(Upot/kT) >[BR]",
1307 " Delta G = G(N,p,T) - G_idgas(N,p,T) = kT ln < e^(Upot/kT) >[BR]",
1308 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
1309 "the average is over the ensemble (or time in a trajectory).",
1310 "Note that this is in principle",
1311 "only correct when averaging over the whole (Boltzmann) ensemble",
1312 "and using the potential energy. This also allows for an entropy",
1313 "estimate using:[BR]",
1314 " Delta S(N,V,T) = S(N,V,T) - S_idgas(N,V,T) = (<Upot> - Delta A)/T[BR]",
1315 " Delta S(N,p,T) = S(N,p,T) - S_idgas(N,p,T) = (<Upot> + pV - Delta G)/T",
1316 "[PAR]",
1318 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
1319 "difference is calculated dF = -kT ln < e ^ -(EB-EA)/kT >A ,",
1320 "where EA and EB are the energies from the first and second energy",
1321 "files, and the average is over the ensemble A. [BB]NOTE[bb] that",
1322 "the energies must both be calculated from the same trajectory."
1325 static bool bSum=FALSE,bFee=FALSE,bPrAll=FALSE,bFluct=FALSE;
1326 static bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE;
1327 static int skip=0,nmol=1,nconstr=0,nbmin=5,nbmax=5;
1328 static real reftemp=300.0,ezero=0;
1329 t_pargs pa[] = {
1330 { "-fee", FALSE, etBOOL, {&bFee},
1331 "Do a free energy estimate" },
1332 { "-fetemp", FALSE, etREAL,{&reftemp},
1333 "Reference temperature for free energy calculation" },
1334 { "-zero", FALSE, etREAL, {&ezero},
1335 "Subtract a zero-point energy" },
1336 { "-sum", FALSE, etBOOL, {&bSum},
1337 "Sum the energy terms selected rather than display them all" },
1338 { "-dp", FALSE, etBOOL, {&bDp},
1339 "Print energies in high precision" },
1340 { "-nbmin", FALSE, etINT, {&nbmin},
1341 "Minimum number of blocks for error estimate" },
1342 { "-nbmax", FALSE, etINT, {&nbmax},
1343 "Maximum number of blocks for error estimate" },
1344 { "-mutot",FALSE, etBOOL, {&bMutot},
1345 "Compute the total dipole moment from the components" },
1346 { "-skip", FALSE, etINT, {&skip},
1347 "Skip number of frames between data points" },
1348 { "-aver", FALSE, etBOOL, {&bPrAll},
1349 "Also print the exact average and rmsd stored in the energy frames (only when 1 term is requested)" },
1350 { "-nmol", FALSE, etINT, {&nmol},
1351 "Number of molecules in your sample: the energies are divided by this number" },
1352 { "-nconstr", FALSE, etINT, {&nconstr},
1353 "Number of constraints per molecule. Necessary for calculating the heat capacity" },
1354 { "-fluc", FALSE, etBOOL, {&bFluct},
1355 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
1356 { "-orinst", FALSE, etBOOL, {&bOrinst},
1357 "Analyse instantaneous orientation data" },
1358 { "-ovec", FALSE, etBOOL, {&bOvec},
1359 "Also plot the eigenvectors with -oten" }
1361 char *drleg[] = {
1362 "Running average",
1363 "Instantaneous"
1365 static const char *setnm[] = {
1366 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
1367 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
1368 "Volume", "Pressure"
1371 FILE *out,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
1372 FILE **drout;
1373 ener_file_t fp;
1374 int timecheck=0;
1375 gmx_mtop_t mtop;
1376 gmx_localtop_t *top=NULL;
1377 t_inputrec ir;
1378 t_energy **ee;
1379 enerdata_t edat;
1380 gmx_enxnm_t *enm=NULL;
1381 t_enxframe *frame,*fr=NULL;
1382 int cur=0;
1383 #define NEXT (1-cur)
1384 int nre,teller,teller_disre,nfr;
1385 gmx_large_int_t start_step;
1386 int nor=0,nex=0,norfr=0,enx_i=0;
1387 real start_t;
1388 real *bounds=NULL,*violaver=NULL,*oobs=NULL,*orient=NULL,*odrms=NULL;
1389 int *index=NULL,*pair=NULL,norsel=0,*orsel=NULL,*or_label=NULL;
1390 int nbounds=0,npairs;
1391 bool bDisRe,bDRAll,bORA,bORT,bODA,bODR,bODT,bORIRE,bOTEN;
1392 bool bFoundStart,bCont,bEDR,bVisco;
1393 double sum,sumaver,sumt,ener,dbl;
1394 double *time=NULL;
1395 real Vaver;
1396 int *set=NULL,i,j,k,nset,sss;
1397 bool *bIsEner=NULL;
1398 char **pairleg,**odtleg,**otenleg;
1399 char **leg=NULL;
1400 char **nms;
1401 char *anm_j,*anm_k,*resnm_j,*resnm_k;
1402 int resnr_j,resnr_k;
1403 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
1404 char buf[256];
1405 output_env_t oenv;
1406 t_filenm fnm[] = {
1407 { efEDR, "-f", NULL, ffREAD },
1408 { efEDR, "-f2", NULL, ffOPTRD },
1409 { efTPX, "-s", NULL, ffOPTRD },
1410 { efXVG, "-o", "energy", ffWRITE },
1411 { efXVG, "-viol", "violaver",ffOPTWR },
1412 { efXVG, "-pairs","pairs", ffOPTWR },
1413 { efXVG, "-ora", "orienta", ffOPTWR },
1414 { efXVG, "-ort", "orientt", ffOPTWR },
1415 { efXVG, "-oda", "orideva", ffOPTWR },
1416 { efXVG, "-odr", "oridevr", ffOPTWR },
1417 { efXVG, "-odt", "oridevt", ffOPTWR },
1418 { efXVG, "-oten", "oriten", ffOPTWR },
1419 { efXVG, "-corr", "enecorr", ffOPTWR },
1420 { efXVG, "-vis", "visco", ffOPTWR },
1421 { efXVG, "-ravg", "runavgdf",ffOPTWR }
1423 #define NFILE asize(fnm)
1424 int npargs;
1425 t_pargs *ppa;
1427 CopyRight(stderr,argv[0]);
1428 npargs = asize(pa);
1429 ppa = add_acf_pargs(&npargs,pa);
1430 parse_common_args(&argc,argv,
1431 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
1432 NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
1434 bDRAll = opt2bSet("-pairs",NFILE,fnm);
1435 bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
1436 bORA = opt2bSet("-ora",NFILE,fnm);
1437 bORT = opt2bSet("-ort",NFILE,fnm);
1438 bODA = opt2bSet("-oda",NFILE,fnm);
1439 bODR = opt2bSet("-odr",NFILE,fnm);
1440 bODT = opt2bSet("-odt",NFILE,fnm);
1441 bORIRE = bORA || bORT || bODA || bODR || bODT;
1442 bOTEN = opt2bSet("-oten",NFILE,fnm);
1444 nset = 0;
1446 snew(frame,2);
1447 fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
1448 do_enxnms(fp,&nre,&enm);
1450 Vaver = -1;
1452 bVisco = opt2bSet("-vis",NFILE,fnm);
1454 if (!bDisRe) {
1455 if (bVisco) {
1456 nset=asize(setnm);
1457 snew(set,nset);
1458 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
1459 for(j=0; j<nset; j++) {
1460 for(i=0; i<nre; i++) {
1461 if (strstr(enm[i].name,setnm[j])) {
1462 set[j]=i;
1463 break;
1466 if (i == nre) {
1467 if (strcasecmp(setnm[j],"Volume")==0) {
1468 printf("Enter the box volume (" unit_volume "): ");
1469 if(1 != scanf("%lf",&dbl))
1471 gmx_fatal(FARGS,"Error reading user input");
1473 Vaver = dbl;
1474 } else
1475 gmx_fatal(FARGS,"Could not find term %s for viscosity calculation",
1476 setnm[j]);
1480 else {
1481 set=select_by_name(nre,enm,&nset);
1483 /* Print all the different units once */
1484 sprintf(buf,"(%s)",enm[set[0]].unit);
1485 for(i=1; i<nset; i++) {
1486 for(j=0; j<i; j++) {
1487 if (strcmp(enm[set[i]].unit,enm[set[j]].unit) == 0) {
1488 break;
1491 if (j == i) {
1492 strcat(buf,", (");
1493 strcat(buf,enm[set[i]].unit);
1494 strcat(buf,")");
1497 out=xvgropen(opt2fn("-o",NFILE,fnm),"Gromacs Energies","Time (ps)",buf,
1498 oenv);
1500 snew(leg,nset+1);
1501 for(i=0; (i<nset); i++)
1502 leg[i] = enm[set[i]].name;
1503 if (bSum) {
1504 leg[nset]=strdup("Sum");
1505 xvgr_legend(out,nset+1,leg,oenv);
1507 else
1508 xvgr_legend(out,nset,leg,oenv);
1510 snew(bIsEner,nset);
1511 for(i=0; (i<nset); i++) {
1512 bIsEner[i] = FALSE;
1513 for (j=0; (j <= F_ETOT); j++)
1514 bIsEner[i] = bIsEner[i] ||
1515 (strcasecmp(interaction_function[j].longname,leg[i]) == 0);
1518 if (bPrAll && nset > 1) {
1519 gmx_fatal(FARGS,"Printing averages can only be done when a single set is selected");
1522 time = NULL;
1524 if (bORIRE || bOTEN)
1525 get_orires_parms(ftp2fn(efTPX,NFILE,fnm),&nor,&nex,&or_label,&oobs);
1527 if (bORIRE) {
1528 if (bOrinst)
1529 enx_i = enxORI;
1530 else
1531 enx_i = enxOR;
1533 if (bORA || bODA)
1534 snew(orient,nor);
1535 if (bODR)
1536 snew(odrms,nor);
1537 if (bORT || bODT) {
1538 fprintf(stderr,"Select the orientation restraint labels you want (-1 is all)\n");
1539 fprintf(stderr,"End your selection with 0\n");
1540 j = -1;
1541 orsel = NULL;
1542 do {
1543 j++;
1544 srenew(orsel,j+1);
1545 if(1 != scanf("%d",&(orsel[j])))
1547 gmx_fatal(FARGS,"Error reading user input");
1549 } while (orsel[j] > 0);
1550 if (orsel[0] == -1) {
1551 fprintf(stderr,"Selecting all %d orientation restraints\n",nor);
1552 norsel = nor;
1553 srenew(orsel,nor);
1554 for(i=0; i<nor; i++)
1555 orsel[i] = i;
1556 } else {
1557 /* Build the selection */
1558 norsel=0;
1559 for(i=0; i<j; i++) {
1560 for(k=0; k<nor; k++)
1561 if (or_label[k] == orsel[i]) {
1562 orsel[norsel] = k;
1563 norsel++;
1564 break;
1566 if (k == nor)
1567 fprintf(stderr,"Orientation restraint label %d not found\n",
1568 orsel[i]);
1571 snew(odtleg,norsel);
1572 for(i=0; i<norsel; i++) {
1573 snew(odtleg[i],256);
1574 sprintf(odtleg[i],"%d",or_label[orsel[i]]);
1576 if (bORT) {
1577 fort=xvgropen(opt2fn("-ort",NFILE,fnm), "Calculated orientations",
1578 "Time (ps)","",oenv);
1579 if (bOrinst)
1580 fprintf(fort,"%s",orinst_sub);
1581 xvgr_legend(fort,norsel,odtleg,oenv);
1583 if (bODT) {
1584 fodt=xvgropen(opt2fn("-odt",NFILE,fnm),
1585 "Orientation restraint deviation",
1586 "Time (ps)","",oenv);
1587 if (bOrinst)
1588 fprintf(fodt,"%s",orinst_sub);
1589 xvgr_legend(fodt,norsel,odtleg,oenv);
1593 if (bOTEN) {
1594 foten=xvgropen(opt2fn("-oten",NFILE,fnm),
1595 "Order tensor","Time (ps)","",oenv);
1596 snew(otenleg,bOvec ? nex*12 : nex*3);
1597 for(i=0; i<nex; i++) {
1598 for(j=0; j<3; j++) {
1599 sprintf(buf,"eig%d",j+1);
1600 otenleg[(bOvec ? 12 : 3)*i+j] = strdup(buf);
1602 if (bOvec) {
1603 for(j=0; j<9; j++) {
1604 sprintf(buf,"vec%d%s",j/3+1,j%3==0 ? "x" : (j%3==1 ? "y" : "z"));
1605 otenleg[12*i+3+j] = strdup(buf);
1609 xvgr_legend(foten,bOvec ? nex*12 : nex*3,otenleg,oenv);
1612 else {
1613 nbounds=get_bounds(ftp2fn(efTPX,NFILE,fnm),&bounds,&index,&pair,&npairs,
1614 &mtop,&top,&ir);
1615 snew(violaver,npairs);
1616 out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
1617 "Time (ps)","nm",oenv);
1618 xvgr_legend(out,2,drleg,oenv);
1619 if (bDRAll) {
1620 fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
1621 "Time (ps)","Distance (nm)",oenv);
1622 if (output_env_get_print_xvgr_codes(oenv))
1623 fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
1624 ir.dr_tau);
1628 /* Initiate energies and set them to zero */
1629 edat.nsteps = 0;
1630 edat.npoints = 0;
1631 edat.nframes = 0;
1632 edat.step = NULL;
1633 edat.steps = NULL;
1634 edat.points = NULL;
1635 snew(edat.s,nset);
1637 /* Initiate counters */
1638 teller = 0;
1639 teller_disre = 0;
1640 bFoundStart = FALSE;
1641 start_step = 0;
1642 start_t = 0;
1643 do {
1644 /* This loop searches for the first frame (when -b option is given),
1645 * or when this has been found it reads just one energy frame
1647 do {
1648 bCont = do_enx(fp,&(frame[NEXT]));
1650 if (bCont) {
1651 timecheck = check_times(frame[NEXT].t);
1653 } while (bCont && (timecheck < 0));
1655 if ((timecheck == 0) && bCont) {
1656 /* We read a valid frame, so we can use it */
1657 fr = &(frame[NEXT]);
1659 if (fr->nre > 0) {
1660 /* The frame contains energies, so update cur */
1661 cur = NEXT;
1663 if (edat.nframes % 1000 == 0)
1665 srenew(edat.step,edat.nframes+1000);
1666 srenew(edat.steps,edat.nframes+1000);
1667 srenew(edat.points,edat.nframes+1000);
1668 for(i=0; i<nset; i++)
1670 srenew(edat.s[i].ener,edat.nframes+1000);
1671 srenew(edat.s[i].es ,edat.nframes+1000);
1675 nfr = edat.nframes;
1676 edat.step[nfr] = fr->step;
1678 if (!bFoundStart)
1680 bFoundStart = TRUE;
1681 /* Initiate the previous step data */
1682 start_step = fr->step;
1683 start_t = fr->t;
1684 /* Initiate the energy sums */
1685 edat.steps[nfr] = 1;
1686 edat.points[nfr] = 1;
1687 for(i=0; i<nset; i++)
1689 sss = set[i];
1690 edat.s[i].es[nfr].sum = fr->ener[sss].e;
1691 edat.s[i].es[nfr].sum2 = 0;
1693 edat.nsteps = 1;
1694 edat.npoints = 1;
1696 else
1698 edat.steps[nfr] = fr->nsteps;
1700 if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
1702 if (fr->nsum <= 1)
1704 edat.points[nfr] = 1;
1705 for(i=0; i<nset; i++)
1707 sss = set[i];
1708 edat.s[i].es[nfr].sum = fr->ener[sss].e;
1709 edat.s[i].es[nfr].sum2 = 0;
1711 edat.npoints += 1;
1713 else
1715 edat.points[nfr] = fr->nsum;
1716 for(i=0; i<nset; i++)
1718 sss = set[i];
1719 edat.s[i].es[nfr].sum = fr->ener[sss].esum;
1720 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
1722 edat.npoints += fr->nsum;
1725 else
1727 /* The interval does not match fr->nsteps:
1728 * can not do exact averages.
1730 edat.npoints = 0;
1732 edat.nsteps = fr->step - start_step + 1;
1735 for(i=0; i<nset; i++)
1737 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
1741 * Define distance restraint legends. Can only be done after
1742 * the first frame has been read... (Then we know how many there are)
1744 if (bDisRe && bDRAll && !leg && (fr->ndisre > 0)) {
1745 t_iatom *fa;
1746 t_iparams *ip;
1748 fa = top->idef.il[F_DISRES].iatoms;
1749 ip = top->idef.iparams;
1751 if (fr->ndisre != top->idef.il[F_DISRES].nr/3)
1752 gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
1753 fr->ndisre,top->idef.il[F_DISRES].nr/3);
1755 snew(pairleg,fr->ndisre);
1756 for(i=0; i<fr->ndisre; i++) {
1757 snew(pairleg[i],30);
1758 j=fa[3*i+1];
1759 k=fa[3*i+2];
1760 gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
1761 gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
1762 sprintf(pairleg[i],"%d %s %d %s (%d)",
1763 resnr_j+1,anm_j,resnr_k+1,anm_k,
1764 ip[fa[3*i]].disres.label);
1766 set=select_it(fr->ndisre,pairleg,&nset);
1767 snew(leg,2*nset);
1768 for(i=0; (i<nset); i++) {
1769 snew(leg[2*i],32);
1770 sprintf(leg[2*i], "a %s",pairleg[set[i]]);
1771 snew(leg[2*i+1],32);
1772 sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
1774 xvgr_legend(fp_pairs,2*nset,leg,oenv);
1778 * Store energies for analysis afterwards...
1780 if (!bDisRe && (fr->nre > 0)) {
1781 if (edat.nframes % 1000 == 0) {
1782 srenew(time,edat.nframes+1000);
1784 time[edat.nframes] = fr->t;
1785 edat.nframes++;
1788 * Printing time, only when we do not want to skip frames
1790 if (!skip || teller % skip == 0) {
1791 if (bDisRe) {
1792 /*******************************************
1793 * D I S T A N C E R E S T R A I N T S
1794 *******************************************/
1795 if (fr->ndisre > 0) {
1796 print_time(out,fr->t);
1797 if (violaver == NULL)
1798 snew(violaver,fr->ndisre);
1800 /* Subtract bounds from distances, to calculate violations */
1801 calc_violations(fr->disre_rt,fr->disre_rm3tav,
1802 nbounds,pair,bounds,violaver,&sumt,&sumaver);
1804 fprintf(out," %8.4f %8.4f\n",sumaver,sumt);
1805 if (bDRAll) {
1806 print_time(fp_pairs,fr->t);
1807 for(i=0; (i<nset); i++) {
1808 sss=set[i];
1809 fprintf(fp_pairs," %8.4f",
1810 mypow(fr->disre_rm3tav[sss],minthird));
1811 fprintf(fp_pairs," %8.4f",
1812 fr->disre_rt[sss]);
1814 fprintf(fp_pairs,"\n");
1816 teller_disre++;
1819 /*******************************************
1820 * E N E R G I E S
1821 *******************************************/
1822 else {
1823 if (fr->nre > 0) {
1824 if (bPrAll)
1826 /* We skip frames with single points (usually only the first frame),
1827 * since they would result in an average plot with outliers.
1829 if (fr->nsum > 1) {
1830 print_time(out,fr->t);
1831 print1(out,bDp,fr->ener[set[0]].e);
1832 print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
1833 print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
1834 fprintf(out,"\n");
1837 else
1839 print_time(out,fr->t);
1840 if (bSum)
1842 sum = 0;
1843 for(i=0; i<nset; i++)
1845 sum += fr->ener[set[i]].e;
1847 print1(out,bDp,sum/nmol-ezero);
1849 else
1851 for(i=0; (i<nset); i++)
1853 if (bIsEner[i])
1855 print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
1857 else
1859 print1(out,bDp,fr->ener[set[i]].e);
1863 fprintf(out,"\n");
1866 if (bORIRE && fr->nblock>enx_i && fr->nr[enx_i]>0) {
1867 if (fr->nr[enx_i] != nor)
1868 gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)",fr->nr[enx_i],nor);
1869 if (bORA || bODA)
1870 for(i=0; i<nor; i++)
1871 orient[i] += fr->block[enx_i][i];
1872 if (bODR)
1873 for(i=0; i<nor; i++)
1874 odrms[i] += sqr(fr->block[enx_i][i]-oobs[i]);
1875 if (bORT) {
1876 fprintf(fort," %10f",fr->t);
1877 for(i=0; i<norsel; i++)
1878 fprintf(fort," %g",fr->block[enx_i][orsel[i]]);
1879 fprintf(fort,"\n");
1881 if (bODT) {
1882 fprintf(fodt," %10f",fr->t);
1883 for(i=0; i<norsel; i++)
1884 fprintf(fodt," %g",fr->block[enx_i][orsel[i]]-oobs[orsel[i]]);
1885 fprintf(fodt,"\n");
1887 norfr++;
1889 if (bOTEN && fr->nblock>enxORT) {
1890 if (fr->nr[enxORT] != nex*12)
1891 gmx_fatal(FARGS,"Number of orientation experiments in energy file (%g) does not match with the topology (%d)",fr->nr[enxORT]/12,nex);
1892 fprintf(foten," %10f",fr->t);
1893 for(i=0; i<nex; i++)
1894 for(j=0; j<(bOvec?12:3); j++)
1895 fprintf(foten," %g",fr->block[enxORT][i*12+j]);
1896 fprintf(foten,"\n");
1901 } while (bCont && (timecheck == 0));
1903 fprintf(stderr,"\n");
1904 close_enx(fp);
1906 ffclose(out);
1908 if (bDRAll)
1909 ffclose(fp_pairs);
1911 if (bORT)
1912 ffclose(fort);
1913 if (bODT)
1914 ffclose(fodt);
1915 if (bORA) {
1916 out = xvgropen(opt2fn("-ora",NFILE,fnm),
1917 "Average calculated orientations",
1918 "Restraint label","",oenv);
1919 if (bOrinst)
1920 fprintf(out,"%s",orinst_sub);
1921 for(i=0; i<nor; i++)
1922 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr);
1923 ffclose(out);
1925 if (bODA) {
1926 out = xvgropen(opt2fn("-oda",NFILE,fnm),
1927 "Average restraint deviation",
1928 "Restraint label","",oenv);
1929 if (bOrinst)
1930 fprintf(out,"%s",orinst_sub);
1931 for(i=0; i<nor; i++)
1932 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr-oobs[i]);
1933 ffclose(out);
1935 if (bODR) {
1936 out = xvgropen(opt2fn("-odr",NFILE,fnm),
1937 "RMS orientation restraint deviations",
1938 "Restraint label","",oenv);
1939 if (bOrinst)
1940 fprintf(out,"%s",orinst_sub);
1941 for(i=0; i<nor; i++)
1942 fprintf(out,"%5d %g\n",or_label[i],sqrt(odrms[i]/norfr));
1943 ffclose(out);
1945 if (bOTEN)
1946 ffclose(foten);
1948 if (bDisRe) {
1949 analyse_disre(opt2fn("-viol",NFILE,fnm),
1950 teller_disre,violaver,bounds,index,pair,nbounds,oenv);
1951 } else {
1952 analyse_ener(opt2bSet("-corr",NFILE,fnm),opt2fn("-corr",NFILE,fnm),
1953 bFee,bSum,bFluct,opt2parg_bSet("-nmol",npargs,ppa),
1954 bVisco,opt2fn("-vis",NFILE,fnm),
1955 nmol,nconstr,start_step,start_t,frame[cur].step,frame[cur].t,
1956 time,reftemp,&edat,
1957 nset,set,bIsEner,leg,enm,Vaver,ezero,nbmin,nbmax,
1958 oenv);
1960 if (opt2bSet("-f2",NFILE,fnm)) {
1961 fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
1962 reftemp, nset, set, leg, &edat, time ,oenv);
1966 const char *nxy = "-nxy";
1968 do_view(oenv,opt2fn("-o",NFILE,fnm),nxy);
1969 do_view(oenv,opt2fn_null("-ravg",NFILE,fnm),nxy);
1970 do_view(oenv,opt2fn_null("-ora",NFILE,fnm),nxy);
1971 do_view(oenv,opt2fn_null("-ort",NFILE,fnm),nxy);
1972 do_view(oenv,opt2fn_null("-oda",NFILE,fnm),nxy);
1973 do_view(oenv,opt2fn_null("-odr",NFILE,fnm),nxy);
1974 do_view(oenv,opt2fn_null("-odt",NFILE,fnm),nxy);
1975 do_view(oenv,opt2fn_null("-oten",NFILE,fnm),nxy);
1977 thanx(stderr);
1979 return 0;