1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
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
34 * Green Red Orange Magenta Azure Cyan Skyblue
45 #include "gmx_fatal.h"
59 #include "mtop_util.h"
63 static real minthird=-1.0/3.0,minsixth=-1.0/6.0;
81 gmx_large_int_t nsteps;
82 gmx_large_int_t npoints;
90 static double mypow(double x,double y)
98 static int *select_it(int nre,char *nm[],int *nset)
103 gmx_bool bVerbose = TRUE;
105 if ((getenv("VERBOSE")) != NULL)
108 fprintf(stderr,"Select the terms you want from the following list\n");
109 fprintf(stderr,"End your selection with 0\n");
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");
121 if(1 != scanf("%d",&n))
123 gmx_fatal(FARGS,"Error reading user input");
125 if ((n>0) && (n<=nre))
130 for(i=(*nset)=0; (i<nre); i++)
139 static int strcount(const char *s1,const char *s2)
142 while (s1 && s2 && (toupper(s1[n]) == toupper(s2[n])))
147 static void chomp(char *buf)
149 int len = strlen(buf);
151 while ((len > 0) && (buf[len-1] == '\n')) {
157 static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
160 int n,k,kk,j,i,nmatch,nind,nss;
162 gmx_bool bEOF,bVerbose = TRUE,bLong=FALSE;
163 char *ptr,buf[STRLEN];
164 const char *fm4="%3d %-14s";
165 const char *fm2="%3d %-34s";
168 if ((getenv("VERBOSE")) != NULL)
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");
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) {
188 fprintf(stderr,"\n");
191 for(kk=k; kk<k+4; kk++) {
192 if (kk < nre && strlen(nm[kk].name) > 14) {
200 fprintf(stderr,fm4,k+1,newnm[k]);
206 fprintf(stderr,fm2,k+1,newnm[k]);
215 fprintf(stderr,"\n\n");
221 while (!bEOF && (fgets2(buf,STRLEN-1,stdin))) {
222 /* Remove newlines */
228 /* Empty line means end of input */
229 bEOF = (strlen(buf) == 0);
234 /* First try to read an integer */
235 nss = sscanf(ptr,"%d",&nind);
237 /* Zero means end of input */
240 } else if ((1<=nind) && (nind<=nre)) {
243 fprintf(stderr,"number %d is out of range\n",nind);
247 /* Now try to read a string */
250 for(nind=0; nind<nre; nind++) {
251 if (gmx_strcasecmp(newnm[nind],ptr) == 0) {
259 for(nind=0; nind<nre; nind++) {
260 if (gmx_strncasecmp(newnm[nind],ptr,i) == 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) {
275 } while (!bEOF && (ptr && (strlen(ptr) > 0)));
280 for(i=(*nset)=0; (i<nre); i++)
287 gmx_fatal(FARGS,"No energy terms selected");
289 for(i=0; (i<nre); i++)
296 static void get_orires_parms(const char *topnm,
297 int *nor,int *nex,int **label,real **obs)
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;
317 gmx_fatal(FARGS,"No orientation restraints in topology!\n");
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",
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)
338 t_functype *functype;
340 int natoms,i,j,k,type,ftype,natom;
348 read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,mtop);
350 top = gmx_mtop_generate_local_top(mtop,ir);
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;
359 gmx_fatal(FARGS,"No distance restraints in topology!\n");
361 /* Allocate memory */
366 /* Fill the bound array */
368 for(i=0; (i<top->idef.ntypes); i++) {
370 if (ftype == F_DISRES) {
372 label1 = ip[i].disres.label;
373 b[nb] = ip[i].disres.up1;
380 /* Fill the index array */
382 disres = &(top->idef.il[F_DISRES]);
383 iatom = disres->iatoms;
384 for(i=j=k=0; (i<disres->nr); ) {
386 ftype = top->idef.functype[type];
387 natom = interaction_function[ftype].nratoms+1;
388 if (label1 != top->idef.iparams[type].disres.label) {
390 label1 = top->idef.iparams[type].disres.label;
399 gmx_incons("get_bounds for distance restraints");
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;
412 double rsum,rav,sumaver,sumt;
416 for(i=0; (i<nb); i++) {
419 for(j=index[i]; (j<index[i+1]); j++) {
421 viol[j] += mypow(rt[j],-3.0);
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]);
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)
441 double sum,sumt,sumaver;
444 /* Subtract bounds from distances, to calculate violations */
445 calc_violations(violaver,violaver,
446 nbounds,pair,bounds,NULL,&sumt,&sumaver);
449 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
451 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",
454 vout=xvgropen(voutfn,"r\\S-3\\N average violations","DR Index","nm",
458 for(i=0; (i<nbounds); i++) {
459 /* Do ensemble averaging */
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]);
466 sum = max(sum,sumaver);
467 fprintf(vout,"%10d %10.5e\n",index[i],sumaver);
470 for(j=0; (j<dr.ndr); j++)
471 fprintf(vout,"%10d %10.5e\n",j,mypow(violaver[j]/nframes,minthird));
475 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
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)
488 double av[4],avold[4];
495 dt = (time[1]-time[0]);
498 for(i=0; i<=nsets; i++)
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++)
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]));
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++) {
521 fprintf(fp0," %10g",av[m]);
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);
546 gmx_large_int_t nst_min;
549 static void clear_ee_sum(ee_sum_t *ees)
557 static void add_ee_sum(ee_sum_t *ees,double sum,int np)
563 static void add_ee_av(ee_sum_t *ees)
567 av = ees->sum/ees->np;
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)
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);
589 if (eee->b == 1 || eee->nst < eee->nst_min)
591 eee->nst_min = eee->nst;
596 static void calc_averages(int nset,enerdata_t *edat,int nbmin,int nbmax)
599 double sum,sum2,sump,see2;
600 gmx_large_int_t steps,np,p,bound_nb;
604 double x,sx,sy,sxx,sxy;
607 /* Check if we have exact statistics over all points */
608 for(i=0; i<nset; 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.
618 for(f=0; f<edat->nframes && !ed->bExactStat; f++)
620 if (ed->ener[i] != 0)
624 ed->bExactStat = (ed->es[f].sum != 0);
628 ed->bExactStat = TRUE;
634 for(i=0; i<nset; i++)
645 for(nb=nbmin; nb<=nbmax; nb++)
648 clear_ee_sum(&eee[nb].sum);
652 for(f=0; f<edat->nframes; f++)
658 /* Add the sum and the sum of variances to the totals. */
664 sum2 += dsqr(sum/np - (sum + es->sum)/(np + p))
670 /* Add a single value to the sum and sum of squares. */
676 /* sum has to be increased after sum2 */
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);
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)
706 eee[nb].nst += edat->step[f] - edat->step[f-1];
710 add_ee_sum(&eee[nb].sum,es->sum,edat->points[f]);
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)
724 edat->s[i].av = sum/np;
727 edat->s[i].rmsd = sqrt(sum2/np);
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);
740 edat->s[i].slope = 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.
752 char buf1[STEPSTRSIZE],buf2[STEPSTRSIZE];
753 fprintf(debug,"Requested %d blocks, we have %d blocks, min %s nsteps %s\n",
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);
766 edat->s[i].ee = sqrt(see2/nee);
776 static enerdata_t *calc_sum(int nset,enerdata_t *edat,int nbmin,int nbmax)
787 snew(s->ener,esum->nframes);
788 snew(s->es ,esum->nframes);
790 s->bExactStat = TRUE;
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++)
804 for(i=0; i<nset; i++)
806 sum += edat->s[i].ener[f];
810 for(i=0; i<nset; i++)
812 sum += edat->s[i].es[f].sum;
818 calc_averages(1,esum,nbmin,nbmax);
823 static char *ee_pr(double ee,char *buf)
830 sprintf(buf,"%s","--");
834 /* Round to two decimals by printing. */
835 sprintf(tmp,"%.1e",ee);
836 sscanf(tmp,"%lf",&rnd);
837 sprintf(buf,"%g",rnd);
843 static void analyse_ener(gmx_bool bCorr,const char *corrfn,
844 gmx_bool bFee,gmx_bool bSum,gmx_bool bFluct,
845 gmx_bool bVisco,const char *visfn,int nmol,
846 gmx_large_int_t start_step,double start_t,
847 gmx_large_int_t step,double t,
848 double time[], real reftemp,
850 int nset,int set[],gmx_bool *bIsEner,
851 char **leg,gmx_enxnm_t *enm,
852 real Vaver,real ezero,
854 const output_env_t oenv)
857 /* Check out the printed manual for equations! */
858 double Dt,aver,stddev,errest,delta_t,totaldrift;
859 enerdata_t *esum=NULL;
860 real xxx,integral,intBulk;
861 real sfrac,oldfrac,diffsum,diffav,fstep,pr_aver,pr_stddev,pr_errest;
862 double beta=0,expE,expEtot,*fee=NULL;
863 gmx_large_int_t nsteps;
864 int nexact,nnotexact;
866 real Temp=-1,Pres=-1,VarV=-1,VarT=-1,VarEtot=-1,AvEtot=0;
869 char buf[256],eebuf[100];
871 nsteps = step - start_step + 1;
873 fprintf(stdout,"Not enough steps (%s) for statistics\n",
874 gmx_step_str(nsteps,buf));
877 /* Calculate the time difference */
878 delta_t = t - start_t;
880 fprintf(stdout,"\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
881 gmx_step_str(nsteps,buf),start_t,t,nset);
883 calc_averages(nset,edat,nbmin,nbmax);
886 esum = calc_sum(nset,edat,nbmin,nbmax);
889 if (edat->npoints == 0) {
895 for(i=0; (i<nset); i++) {
896 if (edat->s[i].bExactStat) {
904 if (nnotexact == 0) {
905 fprintf(stdout,"All statistics are over %s points\n",
906 gmx_step_str(edat->npoints,buf));
907 } else if (nexact == 0 || edat->npoints == edat->nframes) {
908 fprintf(stdout,"All statistics are over %d points (frames)\n",
911 fprintf(stdout,"The term%s",nnotexact==1 ? "" : "s");
912 for(i=0; (i<nset); i++) {
913 if (!edat->s[i].bExactStat) {
914 fprintf(stdout," '%s'",leg[i]);
917 fprintf(stdout," %s has statistics over %d points (frames)\n",
918 nnotexact==1 ? "is" : "are",edat->nframes);
919 fprintf(stdout,"All other statistics are over %s points\n",
920 gmx_step_str(edat->npoints,buf));
922 fprintf(stdout,"\n");
924 fprintf(stdout,"%-24s %10s %10s %10s %10s",
925 "Energy","Average","Err.Est.","RMSD","Tot-Drift");
927 fprintf(stdout," %10s\n","-kT ln<e^(E/kT)>");
929 fprintf(stdout,"\n");
930 fprintf(stdout,"-------------------------------------------------------------------------------\n");
932 /* Initiate locals, only used with -sum */
935 beta = 1.0/(BOLTZ*reftemp);
938 for(i=0; (i<nset); i++) {
939 aver = edat->s[i].av;
940 stddev = edat->s[i].rmsd;
941 errest = edat->s[i].ee;
945 for(j=0; (j<edat->nframes); j++) {
946 expE += exp(beta*(edat->s[i].ener[j] - aver)/nmol);
949 expEtot+=expE/edat->nframes;
951 fee[i] = log(expE/edat->nframes)/beta + aver/nmol;
953 if (strstr(leg[i],"empera") != NULL) {
956 } else if (strstr(leg[i],"olum") != NULL) {
959 } else if (strstr(leg[i],"essure") != NULL) {
961 } else if (strstr(leg[i],"otal") != NULL) {
962 VarEtot = sqr(stddev);
966 pr_aver = aver/nmol-ezero;
967 pr_stddev = stddev/nmol;
968 pr_errest = errest/nmol;
976 /* Multiply the slope in steps with the number of steps taken */
977 totaldrift = (edat->nsteps - 1)*edat->s[i].slope;
983 fprintf(stdout,"%-24s %10g %10s %10g %10g",
984 leg[i],pr_aver,ee_pr(pr_errest,eebuf),pr_stddev,totaldrift);
986 fprintf(stdout," %10g",fee[i]);
988 fprintf(stdout," (%s)\n",enm[set[i]].unit);
991 for(j=0; (j<edat->nframes); j++)
992 edat->s[i].ener[j] -= aver;
996 totaldrift = (edat->nsteps - 1)*esum->s[0].slope;
997 fprintf(stdout,"%-24s %10g %10s %10s %10g (%s)",
998 "Total",esum->s[0].av/nmol,ee_pr(esum->s[0].ee/nmol,eebuf),
999 "--",totaldrift/nmol,enm[set[0]].unit);
1000 /* pr_aver,pr_stddev,a,totaldrift */
1002 fprintf(stdout," %10g %10g\n",
1003 log(expEtot)/beta + esum->s[0].av/nmol,log(expEtot)/beta);
1005 fprintf(stdout,"\n");
1007 /* Do correlation function */
1008 if (edat->nframes > 1)
1010 Dt = delta_t/(edat->nframes - 1);
1017 const char* leg[] = { "Shear", "Bulk" };
1022 /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
1024 /* Symmetrise tensor! (and store in first three elements)
1025 * And subtract average pressure!
1028 for(i=0; i<12; i++) {
1029 snew(eneset[i],edat->nframes);
1032 for(i=0; i<3; i++) {
1033 snew(enesum[i],edat->nframes);
1035 for(i=0; (i<edat->nframes); i++) {
1036 eneset[0][i] = 0.5*(edat->s[1].ener[i]+edat->s[3].ener[i]);
1037 eneset[1][i] = 0.5*(edat->s[2].ener[i]+edat->s[6].ener[i]);
1038 eneset[2][i] = 0.5*(edat->s[5].ener[i]+edat->s[7].ener[i]);
1039 for(j=3; j<=11; j++) {
1040 eneset[j][i] = edat->s[j].ener[i];
1042 eneset[11][i] -= Pres;
1043 enesum[0][i] = 0.5*(edat->s[1].es[i].sum+edat->s[3].es[i].sum);
1044 enesum[1][i] = 0.5*(edat->s[2].es[i].sum+edat->s[6].es[i].sum);
1045 enesum[2][i] = 0.5*(edat->s[5].es[i].sum+edat->s[7].es[i].sum);
1048 einstein_visco("evisco.xvg","eviscoi.xvg",
1049 3,edat->nframes,enesum,Vaver,Temp,nsteps,time,oenv);
1051 /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
1052 /* Do it for shear viscosity */
1053 strcpy(buf,"Shear Viscosity");
1054 low_do_autocorr(corrfn,oenv,buf,edat->nframes,3,
1055 (edat->nframes+1)/2,eneset,Dt,
1056 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1058 /* Now for bulk viscosity */
1059 strcpy(buf,"Bulk Viscosity");
1060 low_do_autocorr(corrfn,oenv,buf,edat->nframes,1,
1061 (edat->nframes+1)/2,&(eneset[11]),Dt,
1062 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1064 factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
1065 fp=xvgropen(visfn,buf,"Time (ps)","\\8h\\4 (cp)",oenv);
1066 xvgr_legend(fp,asize(leg),leg,oenv);
1068 /* Use trapezium rule for integration */
1071 nout = get_acfnout();
1072 if ((nout < 2) || (nout >= edat->nframes/2))
1073 nout = edat->nframes/2;
1074 for(i=1; (i<nout); i++)
1076 integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
1077 intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
1078 fprintf(fp,"%10g %10g %10g\n",(i*Dt),integral,intBulk);
1084 strcpy(buf,"Autocorrelation of Energy Fluctuations");
1086 strcpy(buf,"Energy Autocorrelation");
1088 do_autocorr(corrfn,oenv,buf,edat->nframes,
1090 bSum ? &edat->s[nset-1].ener : eneset,
1091 (delta_t/edat->nframes),eacNormal,FALSE);
1097 static void print_time(FILE *fp,double t)
1099 fprintf(fp,"%12.6f",t);
1102 static void print1(FILE *fp,gmx_bool bDp,real e)
1105 fprintf(fp," %16.12f",e);
1107 fprintf(fp," %10.6f",e);
1110 static void fec(const char *ene2fn, const char *runavgfn,
1111 real reftemp, int nset, int set[], char *leg[],
1112 enerdata_t *edat, double time[],
1113 const output_env_t oenv)
1115 const char* ravgleg[] = { "\\8D\\4E = E\\sB\\N-E\\sA\\N",
1116 "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N" };
1119 int nre,timecheck,step,nenergy,nenergy2,maxenergy;
1125 gmx_enxnm_t *enm=NULL;
1129 /* read second energy file */
1132 enx = open_enx(ene2fn,"r");
1133 do_enxnms(enx,&(fr->nre),&enm);
1135 snew(eneset2,nset+1);
1140 /* This loop searches for the first frame (when -b option is given),
1141 * or when this has been found it reads just one energy frame
1144 bCont = do_enx(enx,fr);
1147 timecheck = check_times(fr->t);
1149 } while (bCont && (timecheck < 0));
1151 /* Store energies for analysis afterwards... */
1152 if ((timecheck == 0) && bCont) {
1154 if ( nenergy2 >= maxenergy ) {
1156 for(i=0; i<=nset; i++)
1157 srenew(eneset2[i],maxenergy);
1159 if (fr->t != time[nenergy2])
1160 fprintf(stderr,"\nWARNING time mismatch %g!=%g at frame %s\n",
1161 fr->t, time[nenergy2], gmx_step_str(fr->step,buf));
1162 for(i=0; i<nset; i++)
1163 eneset2[i][nenergy2] = fr->ener[set[i]].e;
1167 } while (bCont && (timecheck == 0));
1170 if (edat->nframes != nenergy2) {
1171 fprintf(stderr,"\nWARNING file length mismatch %d!=%d\n",
1172 edat->nframes,nenergy2);
1174 nenergy = min(edat->nframes,nenergy2);
1176 /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
1179 fp=xvgropen(runavgfn,"Running average free energy difference",
1180 "Time (" unit_time ")","\\8D\\4E (" unit_energy ")",oenv);
1181 xvgr_legend(fp,asize(ravgleg),ravgleg,oenv);
1183 fprintf(stdout,"\n%-24s %10s\n",
1184 "Energy","dF = -kT ln < exp(-(EB-EA)/kT) >A");
1186 beta = 1.0/(BOLTZ*reftemp);
1187 for(i=0; i<nset; i++) {
1188 if (gmx_strcasecmp(leg[i],enm[set[i]].name)!=0)
1189 fprintf(stderr,"\nWARNING energy set name mismatch %s!=%s\n",
1190 leg[i],enm[set[i]].name);
1191 for(j=0; j<nenergy; j++) {
1192 dE = eneset2[i][j] - edat->s[i].ener[j];
1193 sum += exp(-dE*beta);
1195 fprintf(fp,"%10g %10g %10g\n",
1196 time[j], dE, -BOLTZ*reftemp*log(sum/(j+1)) );
1198 aver = -BOLTZ*reftemp*log(sum/nenergy);
1199 fprintf(stdout,"%-24s %10g\n",leg[i],aver);
1206 static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
1207 int *blocks, int *hists, int *samples, int *nlambdas,
1208 const output_env_t oenv)
1210 const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
1211 char title[STRLEN],label_x[STRLEN],label_y[STRLEN], legend[STRLEN];
1213 gmx_bool first=FALSE;
1214 int nblock_hist=0, nblock_dh=0, nblock_dhcoll=0;
1217 double temp=0, start_time=0, delta_time=0, start_lambda=0, delta_lambda=0;
1219 gmx_bool changing_lambda;
1221 /* now count the blocks & handle the global dh data */
1222 for(i=0;i<fr->nblock;i++)
1224 if (fr->block[i].id == enxDHHIST)
1228 else if (fr->block[i].id == enxDH)
1232 else if (fr->block[i].id == enxDHCOLL)
1235 if ( (fr->block[i].nsub < 1) ||
1236 (fr->block[i].sub[0].type != xdr_datatype_double) ||
1237 (fr->block[i].sub[0].nr < 5))
1239 gmx_fatal(FARGS, "Unexpected block data");
1242 /* read the data from the DHCOLL block */
1243 temp = fr->block[i].sub[0].dval[0];
1244 start_time = fr->block[i].sub[0].dval[1];
1245 delta_time = fr->block[i].sub[0].dval[2];
1246 start_lambda = fr->block[i].sub[0].dval[3];
1247 delta_lambda = fr->block[i].sub[0].dval[4];
1248 changing_lambda = (delta_lambda != 0);
1252 if (nblock_hist == 0 && nblock_dh == 0)
1254 /* don't do anything */
1257 if (nblock_hist>0 && nblock_dh>0)
1259 gmx_fatal(FARGS, "This energy file contains both histogram dhdl data and non-histogram dhdl data. Don't know what to do.");
1265 sprintf(title,"%s, %s",dhdl,deltag);
1266 sprintf(label_x,"%s (%s)","Time",unit_time);
1267 sprintf(label_y,"(%s)",unit_energy);
1271 sprintf(title,"N(%s)",deltag);
1272 sprintf(label_x,"%s (%s)",deltag,unit_energy);
1273 sprintf(label_y,"Samples");
1275 *fp_dhdl=xvgropen_type(filename, title, label_x, label_y, exvggtXNY,
1277 if (! changing_lambda)
1279 sprintf(buf,"T = %g (K), %s = %g", temp, lambda, start_lambda);
1283 sprintf(buf,"T = %g (K)", temp);
1285 xvgr_subtitle(*fp_dhdl,buf,oenv);
1291 (*hists)+=nblock_hist;
1292 (*blocks)+=nblock_dh;
1293 (*nlambdas) = nblock_hist+nblock_dh;
1296 /* write the data */
1297 if (nblock_hist > 0)
1299 gmx_large_int_t sum=0;
1301 for(i=0;i<fr->nblock;i++)
1303 t_enxblock *blk=&(fr->block[i]);
1304 if (blk->id==enxDHHIST)
1306 double foreign_lambda, dx;
1308 int nhist, derivative;
1310 /* check the block types etc. */
1311 if ( (blk->nsub < 2) ||
1312 (blk->sub[0].type != xdr_datatype_double) ||
1313 (blk->sub[1].type != xdr_datatype_large_int) ||
1314 (blk->sub[0].nr < 2) ||
1315 (blk->sub[1].nr < 2) )
1317 gmx_fatal(FARGS, "Unexpected block data in file");
1319 foreign_lambda=blk->sub[0].dval[0];
1320 dx=blk->sub[0].dval[1];
1321 nhist=blk->sub[1].lval[0];
1322 derivative=blk->sub[1].lval[1];
1323 for(j=0;j<nhist;j++)
1326 x0=blk->sub[1].lval[2+j];
1330 sprintf(legend, "N(%s(%s=%g) | %s=%g)",
1331 deltag, lambda, foreign_lambda,
1332 lambda, start_lambda);
1336 sprintf(legend, "N(%s | %s=%g)",
1337 dhdl, lambda, start_lambda);
1341 xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv);
1343 for(k=0;k<blk->sub[j+2].nr;k++)
1348 hist=blk->sub[j+2].ival[k];
1351 fprintf(*fp_dhdl,"%g %d\n%g %d\n", xmin, hist,
1355 /* multiple histogram data blocks in one histogram
1356 mean that the second one is the reverse of the first one:
1357 for dhdl derivatives, it's important to know both the
1358 maximum and minimum values */
1364 (*samples) += (int)(sum/nblock_hist);
1370 char **setnames=NULL;
1371 int nnames=nblock_dh;
1373 if (changing_lambda)
1379 snew(setnames, nnames);
1383 if ( changing_lambda && first)
1385 /* lambda is a plotted value */
1386 setnames[j]=gmx_strdup(lambda);
1391 for(i=0;i<fr->nblock;i++)
1393 t_enxblock *blk=&(fr->block[i]);
1394 if (blk->id == enxDH)
1398 /* do the legends */
1400 double foreign_lambda;
1402 derivative=blk->sub[0].ival[0];
1403 foreign_lambda=blk->sub[1].dval[0];
1407 sprintf(buf, "%s %s %g",dhdl,lambda,start_lambda);
1411 sprintf(buf, "%s %s %g",deltag,lambda, foreign_lambda);
1413 setnames[j] = gmx_strdup(buf);
1423 if (len!=blk->sub[2].nr)
1425 gmx_fatal(FARGS, "Length inconsistency in dhdl data");
1434 xvgr_legend(*fp_dhdl, nblock_dh, (const char**)setnames, oenv);
1436 for(i=0;i<nblock_dh;i++)
1446 double time=start_time + delta_time*i;
1448 fprintf(*fp_dhdl,"%.4f", time);
1449 if (fabs(delta_lambda) > 1e-9)
1451 double lambda_now=i*delta_lambda + start_lambda;
1452 fprintf(*fp_dhdl," %.4f", lambda_now);
1454 for(j=0;j<fr->nblock;j++)
1456 t_enxblock *blk=&(fr->block[j]);
1457 if (blk->id == enxDH)
1460 if (blk->sub[2].type == xdr_datatype_float)
1462 value=blk->sub[2].fval[i];
1466 value=blk->sub[2].dval[i];
1468 fprintf(*fp_dhdl," %g", value);
1471 fprintf(*fp_dhdl, "\n");
1477 int gmx_energy(int argc,char *argv[])
1479 const char *desc[] = {
1481 "[TT]g_energy[tt] extracts energy components or distance restraint",
1482 "data from an energy file. The user is prompted to interactively",
1483 "select the energy terms she wants.[PAR]",
1485 "Average, RMSD, and drift are calculated with full precision from the",
1486 "simulation (see printed manual). Drift is calculated by performing",
1487 "a least-squares fit of the data to a straight line. The reported total drift",
1488 "is the difference of the fit at the first and last point.",
1489 "An error estimate of the average is given based on a block averages",
1490 "over 5 blocks using the full-precision averages. The error estimate",
1491 "can be performed over multiple block lengths with the options",
1492 "[TT]-nbmin[tt] and [TT]-nbmax[tt].",
1493 "[BB]Note[bb] that in most cases the energy files contains averages over all",
1494 "MD steps, or over many more points than the number of frames in",
1495 "energy file. This makes the [TT]g_energy[tt] statistics output more accurate",
1496 "than the [TT].xvg[tt] output. When exact averages are not present in the energy",
1497 "file, the statistics mentioned above are simply over the single, per-frame",
1498 "energy values.[PAR]",
1500 "The term fluctuation gives the RMSD around the least-squares fit.[PAR]",
1502 "When the [TT]-viol[tt] option is set, the time averaged",
1503 "violations are plotted and the running time-averaged and",
1504 "instantaneous sum of violations are recalculated. Additionally",
1505 "running time-averaged and instantaneous distances between",
1506 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
1508 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
1509 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
1510 "The first two options plot the orientation, the last three the",
1511 "deviations of the orientations from the experimental values.",
1512 "The options that end on an 'a' plot the average over time",
1513 "as a function of restraint. The options that end on a 't'",
1514 "prompt the user for restraint label numbers and plot the data",
1515 "as a function of time. Option [TT]-odr[tt] plots the RMS",
1516 "deviation as a function of restraint.",
1517 "When the run used time or ensemble averaged orientation restraints,",
1518 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
1519 "not ensemble-averaged orientations and deviations instead of",
1520 "the time and ensemble averages.[PAR]",
1522 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
1523 "tensor for each orientation restraint experiment. With option",
1524 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
1526 "Option [TT]-odh[tt] extracts and plots the free energy data",
1527 "(Hamiltoian differences and/or the Hamiltonian derivative dhdl)",
1528 "from the [TT]ener.edr[tt] file.[PAR]",
1530 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
1531 "difference with an ideal gas state: [BR]",
1532 " [GRK]Delta[grk] A = A(N,V,T) - A_idgas(N,V,T) = kT ln < e^(Upot/kT) >[BR]",
1533 " [GRK]Delta[grk] G = G(N,p,T) - G_idgas(N,p,T) = kT ln < e^(Upot/kT) >[BR]",
1534 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
1535 "the average is over the ensemble (or time in a trajectory).",
1536 "Note that this is in principle",
1537 "only correct when averaging over the whole (Boltzmann) ensemble",
1538 "and using the potential energy. This also allows for an entropy",
1539 "estimate using:[BR]",
1540 " [GRK]Delta[grk] S(N,V,T) = S(N,V,T) - S_idgas(N,V,T) = (<Upot> - [GRK]Delta[grk] A)/T[BR]",
1541 " [GRK]Delta[grk] S(N,p,T) = S(N,p,T) - S_idgas(N,p,T) = (<Upot> + pV - [GRK]Delta[grk] G)/T",
1544 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
1545 "difference is calculated dF = -kT ln < e ^ -(EB-EA)/kT >A ,",
1546 "where EA and EB are the energies from the first and second energy",
1547 "files, and the average is over the ensemble A. [BB]Note[bb] that",
1548 "the energies must both be calculated from the same trajectory."
1551 static gmx_bool bSum=FALSE,bFee=FALSE,bPrAll=FALSE,bFluct=FALSE;
1552 static gmx_bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE;
1553 static int skip=0,nmol=1,nbmin=5,nbmax=5;
1554 static real reftemp=300.0,ezero=0;
1556 { "-fee", FALSE, etBOOL, {&bFee},
1557 "Do a free energy estimate" },
1558 { "-fetemp", FALSE, etREAL,{&reftemp},
1559 "Reference temperature for free energy calculation" },
1560 { "-zero", FALSE, etREAL, {&ezero},
1561 "Subtract a zero-point energy" },
1562 { "-sum", FALSE, etBOOL, {&bSum},
1563 "Sum the energy terms selected rather than display them all" },
1564 { "-dp", FALSE, etBOOL, {&bDp},
1565 "Print energies in high precision" },
1566 { "-nbmin", FALSE, etINT, {&nbmin},
1567 "Minimum number of blocks for error estimate" },
1568 { "-nbmax", FALSE, etINT, {&nbmax},
1569 "Maximum number of blocks for error estimate" },
1570 { "-mutot",FALSE, etBOOL, {&bMutot},
1571 "Compute the total dipole moment from the components" },
1572 { "-skip", FALSE, etINT, {&skip},
1573 "Skip number of frames between data points" },
1574 { "-aver", FALSE, etBOOL, {&bPrAll},
1575 "Also print the exact average and rmsd stored in the energy frames (only when 1 term is requested)" },
1576 { "-nmol", FALSE, etINT, {&nmol},
1577 "Number of molecules in your sample: the energies are divided by this number" },
1578 { "-fluc", FALSE, etBOOL, {&bFluct},
1579 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
1580 { "-orinst", FALSE, etBOOL, {&bOrinst},
1581 "Analyse instantaneous orientation data" },
1582 { "-ovec", FALSE, etBOOL, {&bOvec},
1583 "Also plot the eigenvectors with [TT]-oten[tt]" }
1585 const char* drleg[] = {
1589 static const char *setnm[] = {
1590 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
1591 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
1592 "Volume", "Pressure"
1595 FILE *out=NULL,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
1601 gmx_localtop_t *top=NULL;
1605 gmx_enxnm_t *enm=NULL;
1606 t_enxframe *frame,*fr=NULL;
1608 #define NEXT (1-cur)
1609 int nre,teller,teller_disre,nfr;
1610 gmx_large_int_t start_step;
1611 int nor=0,nex=0,norfr=0,enx_i=0;
1613 real *bounds=NULL,*violaver=NULL,*oobs=NULL,*orient=NULL,*odrms=NULL;
1614 int *index=NULL,*pair=NULL,norsel=0,*orsel=NULL,*or_label=NULL;
1615 int nbounds=0,npairs;
1616 gmx_bool bDisRe,bDRAll,bORA,bORT,bODA,bODR,bODT,bORIRE,bOTEN,bDHDL;
1617 gmx_bool bFoundStart,bCont,bEDR,bVisco;
1618 double sum,sumaver,sumt,ener,dbl;
1621 int *set=NULL,i,j,k,nset,sss;
1622 gmx_bool *bIsEner=NULL;
1623 char **pairleg,**odtleg,**otenleg;
1626 char *anm_j,*anm_k,*resnm_j,*resnm_k;
1627 int resnr_j,resnr_k;
1628 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
1631 t_enxblock *blk=NULL;
1632 t_enxblock *blk_disre=NULL;
1634 int dh_blocks=0, dh_hists=0, dh_samples=0, dh_lambdas=0;
1637 { efEDR, "-f", NULL, ffREAD },
1638 { efEDR, "-f2", NULL, ffOPTRD },
1639 { efTPX, "-s", NULL, ffOPTRD },
1640 { efXVG, "-o", "energy", ffWRITE },
1641 { efXVG, "-viol", "violaver",ffOPTWR },
1642 { efXVG, "-pairs","pairs", ffOPTWR },
1643 { efXVG, "-ora", "orienta", ffOPTWR },
1644 { efXVG, "-ort", "orientt", ffOPTWR },
1645 { efXVG, "-oda", "orideva", ffOPTWR },
1646 { efXVG, "-odr", "oridevr", ffOPTWR },
1647 { efXVG, "-odt", "oridevt", ffOPTWR },
1648 { efXVG, "-oten", "oriten", ffOPTWR },
1649 { efXVG, "-corr", "enecorr", ffOPTWR },
1650 { efXVG, "-vis", "visco", ffOPTWR },
1651 { efXVG, "-ravg", "runavgdf",ffOPTWR },
1652 { efXVG, "-odh", "dhdl" ,ffOPTWR }
1654 #define NFILE asize(fnm)
1658 CopyRight(stderr,argv[0]);
1660 ppa = add_acf_pargs(&npargs,pa);
1661 parse_common_args(&argc,argv,
1662 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
1663 NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
1665 bDRAll = opt2bSet("-pairs",NFILE,fnm);
1666 bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
1667 bORA = opt2bSet("-ora",NFILE,fnm);
1668 bORT = opt2bSet("-ort",NFILE,fnm);
1669 bODA = opt2bSet("-oda",NFILE,fnm);
1670 bODR = opt2bSet("-odr",NFILE,fnm);
1671 bODT = opt2bSet("-odt",NFILE,fnm);
1672 bORIRE = bORA || bORT || bODA || bODR || bODT;
1673 bOTEN = opt2bSet("-oten",NFILE,fnm);
1674 bDHDL = opt2bSet("-odh",NFILE,fnm);
1679 fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
1680 do_enxnms(fp,&nre,&enm);
1684 bVisco = opt2bSet("-vis",NFILE,fnm);
1686 if (!bDisRe && !bDHDL)
1691 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
1692 for(j=0; j<nset; j++) {
1693 for(i=0; i<nre; i++) {
1694 if (strstr(enm[i].name,setnm[j])) {
1700 if (gmx_strcasecmp(setnm[j],"Volume")==0) {
1701 printf("Enter the box volume (" unit_volume "): ");
1702 if(1 != scanf("%lf",&dbl))
1704 gmx_fatal(FARGS,"Error reading user input");
1708 gmx_fatal(FARGS,"Could not find term %s for viscosity calculation",
1715 set=select_by_name(nre,enm,&nset);
1717 /* Print all the different units once */
1718 sprintf(buf,"(%s)",enm[set[0]].unit);
1719 for(i=1; i<nset; i++) {
1720 for(j=0; j<i; j++) {
1721 if (strcmp(enm[set[i]].unit,enm[set[j]].unit) == 0) {
1727 strcat(buf,enm[set[i]].unit);
1731 out=xvgropen(opt2fn("-o",NFILE,fnm),"Gromacs Energies","Time (ps)",buf,
1735 for(i=0; (i<nset); i++)
1736 leg[i] = enm[set[i]].name;
1738 leg[nset]=strdup("Sum");
1739 xvgr_legend(out,nset+1,(const char**)leg,oenv);
1742 xvgr_legend(out,nset,(const char**)leg,oenv);
1745 for(i=0; (i<nset); i++) {
1747 for (j=0; (j <= F_ETOT); j++)
1748 bIsEner[i] = bIsEner[i] ||
1749 (gmx_strcasecmp(interaction_function[j].longname,leg[i]) == 0);
1752 if (bPrAll && nset > 1) {
1753 gmx_fatal(FARGS,"Printing averages can only be done when a single set is selected");
1758 if (bORIRE || bOTEN)
1759 get_orires_parms(ftp2fn(efTPX,NFILE,fnm),&nor,&nex,&or_label,&oobs);
1772 fprintf(stderr,"Select the orientation restraint labels you want (-1 is all)\n");
1773 fprintf(stderr,"End your selection with 0\n");
1779 if(1 != scanf("%d",&(orsel[j])))
1781 gmx_fatal(FARGS,"Error reading user input");
1783 } while (orsel[j] > 0);
1784 if (orsel[0] == -1) {
1785 fprintf(stderr,"Selecting all %d orientation restraints\n",nor);
1788 for(i=0; i<nor; i++)
1791 /* Build the selection */
1793 for(i=0; i<j; i++) {
1794 for(k=0; k<nor; k++)
1795 if (or_label[k] == orsel[i]) {
1801 fprintf(stderr,"Orientation restraint label %d not found\n",
1805 snew(odtleg,norsel);
1806 for(i=0; i<norsel; i++) {
1807 snew(odtleg[i],256);
1808 sprintf(odtleg[i],"%d",or_label[orsel[i]]);
1811 fort=xvgropen(opt2fn("-ort",NFILE,fnm), "Calculated orientations",
1812 "Time (ps)","",oenv);
1814 fprintf(fort,"%s",orinst_sub);
1815 xvgr_legend(fort,norsel,(const char**)odtleg,oenv);
1818 fodt=xvgropen(opt2fn("-odt",NFILE,fnm),
1819 "Orientation restraint deviation",
1820 "Time (ps)","",oenv);
1822 fprintf(fodt,"%s",orinst_sub);
1823 xvgr_legend(fodt,norsel,(const char**)odtleg,oenv);
1828 foten=xvgropen(opt2fn("-oten",NFILE,fnm),
1829 "Order tensor","Time (ps)","",oenv);
1830 snew(otenleg,bOvec ? nex*12 : nex*3);
1831 for(i=0; i<nex; i++) {
1832 for(j=0; j<3; j++) {
1833 sprintf(buf,"eig%d",j+1);
1834 otenleg[(bOvec ? 12 : 3)*i+j] = strdup(buf);
1837 for(j=0; j<9; j++) {
1838 sprintf(buf,"vec%d%s",j/3+1,j%3==0 ? "x" : (j%3==1 ? "y" : "z"));
1839 otenleg[12*i+3+j] = strdup(buf);
1843 xvgr_legend(foten,bOvec ? nex*12 : nex*3,(const char**)otenleg,oenv);
1848 nbounds=get_bounds(ftp2fn(efTPX,NFILE,fnm),&bounds,&index,&pair,&npairs,
1850 snew(violaver,npairs);
1851 out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
1852 "Time (ps)","nm",oenv);
1853 xvgr_legend(out,2,drleg,oenv);
1855 fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
1856 "Time (ps)","Distance (nm)",oenv);
1857 if (output_env_get_print_xvgr_codes(oenv))
1858 fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
1864 /* Initiate energies and set them to zero */
1873 /* Initiate counters */
1876 bFoundStart = FALSE;
1880 /* This loop searches for the first frame (when -b option is given),
1881 * or when this has been found it reads just one energy frame
1884 bCont = do_enx(fp,&(frame[NEXT]));
1887 timecheck = check_times(frame[NEXT].t);
1889 } while (bCont && (timecheck < 0));
1891 if ((timecheck == 0) && bCont) {
1892 /* We read a valid frame, so we can use it */
1893 fr = &(frame[NEXT]);
1896 /* The frame contains energies, so update cur */
1899 if (edat.nframes % 1000 == 0)
1901 srenew(edat.step,edat.nframes+1000);
1902 srenew(edat.steps,edat.nframes+1000);
1903 srenew(edat.points,edat.nframes+1000);
1904 for(i=0; i<nset; i++)
1906 srenew(edat.s[i].ener,edat.nframes+1000);
1907 srenew(edat.s[i].es ,edat.nframes+1000);
1912 edat.step[nfr] = fr->step;
1917 /* Initiate the previous step data */
1918 start_step = fr->step;
1920 /* Initiate the energy sums */
1921 edat.steps[nfr] = 1;
1922 edat.points[nfr] = 1;
1923 for(i=0; i<nset; i++)
1926 edat.s[i].es[nfr].sum = fr->ener[sss].e;
1927 edat.s[i].es[nfr].sum2 = 0;
1934 edat.steps[nfr] = fr->nsteps;
1936 if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
1940 edat.points[nfr] = 1;
1941 for(i=0; i<nset; i++)
1944 edat.s[i].es[nfr].sum = fr->ener[sss].e;
1945 edat.s[i].es[nfr].sum2 = 0;
1951 edat.points[nfr] = fr->nsum;
1952 for(i=0; i<nset; i++)
1955 edat.s[i].es[nfr].sum = fr->ener[sss].esum;
1956 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
1958 edat.npoints += fr->nsum;
1963 /* The interval does not match fr->nsteps:
1964 * can not do exact averages.
1968 edat.nsteps = fr->step - start_step + 1;
1971 for(i=0; i<nset; i++)
1973 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
1977 * Define distance restraint legends. Can only be done after
1978 * the first frame has been read... (Then we know how many there are)
1980 blk_disre=find_block_id_enxframe(fr, enxDISRE, NULL);
1981 if (bDisRe && bDRAll && !leg && blk_disre)
1986 fa = top->idef.il[F_DISRES].iatoms;
1987 ip = top->idef.iparams;
1988 if (blk_disre->nsub != 2 ||
1989 (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
1991 gmx_incons("Number of disre sub-blocks not equal to 2");
1994 ndisre=blk_disre->sub[0].nr ;
1995 if (ndisre != top->idef.il[F_DISRES].nr/3)
1997 gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
1998 ndisre,top->idef.il[F_DISRES].nr/3);
2000 snew(pairleg,ndisre);
2001 for(i=0; i<ndisre; i++)
2003 snew(pairleg[i],30);
2006 gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
2007 gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
2008 sprintf(pairleg[i],"%d %s %d %s (%d)",
2009 resnr_j,anm_j,resnr_k,anm_k,
2010 ip[fa[3*i]].disres.label);
2012 set=select_it(ndisre,pairleg,&nset);
2014 for(i=0; (i<nset); i++)
2017 sprintf(leg[2*i], "a %s",pairleg[set[i]]);
2018 snew(leg[2*i+1],32);
2019 sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
2021 xvgr_legend(fp_pairs,2*nset,(const char**)leg,oenv);
2025 * Store energies for analysis afterwards...
2027 if (!bDisRe && !bDHDL && (fr->nre > 0)) {
2028 if (edat.nframes % 1000 == 0) {
2029 srenew(time,edat.nframes+1000);
2031 time[edat.nframes] = fr->t;
2035 * Printing time, only when we do not want to skip frames
2037 if (!skip || teller % skip == 0) {
2039 /*******************************************
2040 * D I S T A N C E R E S T R A I N T S
2041 *******************************************/
2045 float *disre_rt = blk_disre->sub[0].fval;
2046 float *disre_rm3tav = blk_disre->sub[1].fval;
2048 double *disre_rt = blk_disre->sub[0].dval;
2049 double *disre_rm3tav = blk_disre->sub[1].dval;
2052 print_time(out,fr->t);
2053 if (violaver == NULL)
2054 snew(violaver,ndisre);
2056 /* Subtract bounds from distances, to calculate violations */
2057 calc_violations(disre_rt, disre_rm3tav,
2058 nbounds,pair,bounds,violaver,&sumt,&sumaver);
2060 fprintf(out," %8.4f %8.4f\n",sumaver,sumt);
2062 print_time(fp_pairs,fr->t);
2063 for(i=0; (i<nset); i++) {
2065 fprintf(fp_pairs," %8.4f", mypow(disre_rm3tav[sss],minthird));
2066 fprintf(fp_pairs," %8.4f", disre_rt[sss]);
2068 fprintf(fp_pairs,"\n");
2075 do_dhdl(fr, &fp_dhdl, opt2fn("-odh",NFILE,fnm),
2076 &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas,
2079 /*******************************************
2081 *******************************************/
2086 /* We skip frames with single points (usually only the first frame),
2087 * since they would result in an average plot with outliers.
2090 print_time(out,fr->t);
2091 print1(out,bDp,fr->ener[set[0]].e);
2092 print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
2093 print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
2099 print_time(out,fr->t);
2103 for(i=0; i<nset; i++)
2105 sum += fr->ener[set[i]].e;
2107 print1(out,bDp,sum/nmol-ezero);
2111 for(i=0; (i<nset); i++)
2115 print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
2119 print1(out,bDp,fr->ener[set[i]].e);
2127 /* we first count the blocks that have id 0: the orire blocks */
2129 for(b=0;b<fr->nblock;b++)
2131 if (fr->block[b].id == mde_block_type_orire)
2135 blk = find_block_id_enxframe(fr, enx_i, NULL);
2139 xdr_datatype dt=xdr_datatype_float;
2141 xdr_datatype dt=xdr_datatype_double;
2145 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2147 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2150 vals=blk->sub[0].fval;
2152 vals=blk->sub[0].dval;
2155 if (blk->sub[0].nr != (size_t)nor)
2156 gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)", blk->sub[0].nr);
2159 for(i=0; i<nor; i++)
2160 orient[i] += vals[i];
2164 for(i=0; i<nor; i++)
2165 odrms[i] += sqr(vals[i]-oobs[i]);
2169 fprintf(fort," %10f",fr->t);
2170 for(i=0; i<norsel; i++)
2171 fprintf(fort," %g",vals[orsel[i]]);
2176 fprintf(fodt," %10f",fr->t);
2177 for(i=0; i<norsel; i++)
2178 fprintf(fodt," %g", vals[orsel[i]]-oobs[orsel[i]]);
2183 blk = find_block_id_enxframe(fr, enxORT, NULL);
2187 xdr_datatype dt=xdr_datatype_float;
2189 xdr_datatype dt=xdr_datatype_double;
2193 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2194 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2196 vals=blk->sub[0].fval;
2198 vals=blk->sub[0].dval;
2201 if (blk->sub[0].nr != (size_t)(nex*12))
2202 gmx_fatal(FARGS,"Number of orientation experiments in energy file (%g) does not match with the topology (%d)",
2203 blk->sub[0].nr/12, nex);
2204 fprintf(foten," %10f",fr->t);
2205 for(i=0; i<nex; i++)
2206 for(j=0; j<(bOvec?12:3); j++)
2207 fprintf(foten," %g",vals[i*12+j]);
2208 fprintf(foten,"\n");
2213 } while (bCont && (timecheck == 0));
2215 fprintf(stderr,"\n");
2229 out = xvgropen(opt2fn("-ora",NFILE,fnm),
2230 "Average calculated orientations",
2231 "Restraint label","",oenv);
2233 fprintf(out,"%s",orinst_sub);
2234 for(i=0; i<nor; i++)
2235 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr);
2239 out = xvgropen(opt2fn("-oda",NFILE,fnm),
2240 "Average restraint deviation",
2241 "Restraint label","",oenv);
2243 fprintf(out,"%s",orinst_sub);
2244 for(i=0; i<nor; i++)
2245 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr-oobs[i]);
2249 out = xvgropen(opt2fn("-odr",NFILE,fnm),
2250 "RMS orientation restraint deviations",
2251 "Restraint label","",oenv);
2253 fprintf(out,"%s",orinst_sub);
2254 for(i=0; i<nor; i++)
2255 fprintf(out,"%5d %g\n",or_label[i],sqrt(odrms[i]/norfr));
2263 analyse_disre(opt2fn("-viol",NFILE,fnm),
2264 teller_disre,violaver,bounds,index,pair,nbounds,oenv);
2271 printf("\n\nWrote %d lambda values with %d samples as ",
2272 dh_lambdas, dh_samples);
2275 printf("%d dH histograms ", dh_hists);
2279 printf("%d dH data blocks ", dh_blocks);
2281 printf("to %s\n", opt2fn("-odh",NFILE,fnm));
2286 gmx_fatal(FARGS, "No dH data in %s\n", opt2fn("-f",NFILE,fnm));
2292 analyse_ener(opt2bSet("-corr",NFILE,fnm),opt2fn("-corr",NFILE,fnm),
2294 bVisco,opt2fn("-vis",NFILE,fnm),
2295 nmol,start_step,start_t,frame[cur].step,frame[cur].t,
2297 nset,set,bIsEner,leg,enm,Vaver,ezero,nbmin,nbmax,
2300 if (opt2bSet("-f2",NFILE,fnm)) {
2301 fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
2302 reftemp, nset, set, leg, &edat, time ,oenv);
2306 const char *nxy = "-nxy";
2308 do_view(oenv,opt2fn("-o",NFILE,fnm),nxy);
2309 do_view(oenv,opt2fn_null("-ravg",NFILE,fnm),nxy);
2310 do_view(oenv,opt2fn_null("-ora",NFILE,fnm),nxy);
2311 do_view(oenv,opt2fn_null("-ort",NFILE,fnm),nxy);
2312 do_view(oenv,opt2fn_null("-oda",NFILE,fnm),nxy);
2313 do_view(oenv,opt2fn_null("-odr",NFILE,fnm),nxy);
2314 do_view(oenv,opt2fn_null("-odt",NFILE,fnm),nxy);
2315 do_view(oenv,opt2fn_null("-oten",NFILE,fnm),nxy);
2316 do_view(oenv,opt2fn_null("-odh",NFILE,fnm),nxy);