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 void chomp(char *buf)
141 int len = strlen(buf);
143 while ((len > 0) && (buf[len-1] == '\n')) {
149 static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
152 int n,k,kk,j,i,nmatch,nind,nss;
154 gmx_bool bEOF,bVerbose = TRUE,bLong=FALSE;
155 char *ptr,buf[STRLEN];
156 const char *fm4="%3d %-14s";
157 const char *fm2="%3d %-34s";
160 if ((getenv("VERBOSE")) != NULL)
163 fprintf(stderr,"\n");
164 fprintf(stderr,"Select the terms you want from the following list by\n");
165 fprintf(stderr,"selecting either (part of) the name or the number or a combination.\n");
166 fprintf(stderr,"End your selection with an empty line or a zero.\n");
167 fprintf(stderr,"-------------------------------------------------------------------\n");
171 for(k=0; k<nre; k++) {
172 newnm[k] = strdup(nm[k].name);
173 /* Insert dashes in all the names */
174 while ((ptr = strchr(newnm[k],' ')) != NULL) {
180 fprintf(stderr,"\n");
183 for(kk=k; kk<k+4; kk++) {
184 if (kk < nre && strlen(nm[kk].name) > 14) {
192 fprintf(stderr,fm4,k+1,newnm[k]);
198 fprintf(stderr,fm2,k+1,newnm[k]);
207 fprintf(stderr,"\n\n");
213 while (!bEOF && (fgets2(buf,STRLEN-1,stdin))) {
214 /* Remove newlines */
220 /* Empty line means end of input */
221 bEOF = (strlen(buf) == 0);
226 /* First try to read an integer */
227 nss = sscanf(ptr,"%d",&nind);
229 /* Zero means end of input */
232 } else if ((1<=nind) && (nind<=nre)) {
235 fprintf(stderr,"number %d is out of range\n",nind);
239 /* Now try to read a string */
242 for(nind=0; nind<nre; nind++) {
243 if (gmx_strcasecmp(newnm[nind],ptr) == 0) {
251 for(nind=0; nind<nre; nind++) {
252 if (gmx_strncasecmp(newnm[nind],ptr,i) == 0) {
258 fprintf(stderr,"String '%s' does not match anything\n",ptr);
263 /* Look for the first space, and remove spaces from there */
264 if ((ptr = strchr(ptr,' ')) != NULL) {
267 } while (!bEOF && (ptr && (strlen(ptr) > 0)));
272 for(i=(*nset)=0; (i<nre); i++)
279 gmx_fatal(FARGS,"No energy terms selected");
281 for(i=0; (i<nre); i++)
288 static void get_orires_parms(const char *topnm,
289 int *nor,int *nex,int **label,real **obs)
300 read_tpx(topnm,&ir,box,&natoms,NULL,NULL,NULL,&mtop);
301 top = gmx_mtop_generate_local_top(&mtop,&ir);
303 ip = top->idef.iparams;
304 iatom = top->idef.il[F_ORIRES].iatoms;
306 /* Count how many distance restraint there are... */
307 nb = top->idef.il[F_ORIRES].nr;
309 gmx_fatal(FARGS,"No orientation restraints in topology!\n");
315 for(i=0; i<nb; i+=3) {
316 (*label)[i/3] = ip[iatom[i]].orires.label;
317 (*obs)[i/3] = ip[iatom[i]].orires.obs;
318 if (ip[iatom[i]].orires.ex >= *nex)
319 *nex = ip[iatom[i]].orires.ex+1;
321 fprintf(stderr,"Found %d orientation restraints with %d experiments",
325 static int get_bounds(const char *topnm,
326 real **bounds,int **index,int **dr_pair,int *npairs,
327 gmx_mtop_t *mtop,gmx_localtop_t **ltop,t_inputrec *ir)
330 t_functype *functype;
332 int natoms,i,j,k,type,ftype,natom;
340 read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,mtop);
342 top = gmx_mtop_generate_local_top(mtop,ir);
345 functype = top->idef.functype;
346 ip = top->idef.iparams;
348 /* Count how many distance restraint there are... */
349 nb=top->idef.il[F_DISRES].nr;
351 gmx_fatal(FARGS,"No distance restraints in topology!\n");
353 /* Allocate memory */
358 /* Fill the bound array */
360 for(i=0; (i<top->idef.ntypes); i++) {
362 if (ftype == F_DISRES) {
364 label1 = ip[i].disres.label;
365 b[nb] = ip[i].disres.up1;
372 /* Fill the index array */
374 disres = &(top->idef.il[F_DISRES]);
375 iatom = disres->iatoms;
376 for(i=j=k=0; (i<disres->nr); ) {
378 ftype = top->idef.functype[type];
379 natom = interaction_function[ftype].nratoms+1;
380 if (label1 != top->idef.iparams[type].disres.label) {
382 label1 = top->idef.iparams[type].disres.label;
391 gmx_incons("get_bounds for distance restraints");
399 static void calc_violations(real rt[],real rav3[],int nb,int index[],
400 real bounds[],real *viol,double *st,double *sa)
402 const real sixth=1.0/6.0;
404 double rsum,rav,sumaver,sumt;
408 for(i=0; (i<nb); i++) {
411 for(j=index[i]; (j<index[i+1]); j++) {
413 viol[j] += mypow(rt[j],-3.0);
415 rsum += mypow(rt[j],-6);
417 rsum = max(0.0,mypow(rsum,-sixth)-bounds[i]);
418 rav = max(0.0,mypow(rav, -sixth)-bounds[i]);
427 static void analyse_disre(const char *voutfn, int nframes,
428 real violaver[], real bounds[], int index[],
429 int pair[], int nbounds,
430 const output_env_t oenv)
433 double sum,sumt,sumaver;
436 /* Subtract bounds from distances, to calculate violations */
437 calc_violations(violaver,violaver,
438 nbounds,pair,bounds,NULL,&sumt,&sumaver);
441 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
443 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",
446 vout=xvgropen(voutfn,"r\\S-3\\N average violations","DR Index","nm",
450 for(i=0; (i<nbounds); i++) {
451 /* Do ensemble averaging */
453 for(j=pair[i]; (j<pair[i+1]); j++)
454 sumaver += sqr(violaver[j]/nframes);
455 sumaver = max(0.0,mypow(sumaver,minsixth)-bounds[i]);
458 sum = max(sum,sumaver);
459 fprintf(vout,"%10d %10.5e\n",index[i],sumaver);
462 for(j=0; (j<dr.ndr); j++)
463 fprintf(vout,"%10d %10.5e\n",j,mypow(violaver[j]/nframes,minthird));
467 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
469 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",sum);
471 do_view(oenv,voutfn,"-graphtype bar");
474 static void einstein_visco(const char *fn,const char *fni,int nsets,
475 int nframes,real **sum,
476 real V,real T,int nsteps,double time[],
477 const output_env_t oenv)
480 double av[4],avold[4];
487 dt = (time[1]-time[0]);
490 for(i=0; i<=nsets; i++)
492 fp0=xvgropen(fni,"Shear viscosity integral",
493 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N ps)",oenv);
494 fp1=xvgropen(fn,"Shear viscosity using Einstein relation",
495 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N)",oenv);
496 for(i=1; i<nf4; i++) {
497 fac = dt*nframes/nsteps;
498 for(m=0; m<=nsets; m++)
500 for(j=0; j<nframes-i; j++) {
501 for(m=0; m<nsets; m++) {
502 di = sqr(fac*(sum[m][j+i]-sum[m][j]));
505 av[nsets] += di/nsets;
508 /* Convert to SI for the viscosity */
509 fac = (V*NANO*NANO*NANO*PICO*1e10)/(2*BOLTZMANN*T)/(nframes-i);
510 fprintf(fp0,"%10g",time[i]-time[0]);
511 for(m=0; (m<=nsets); m++) {
513 fprintf(fp0," %10g",av[m]);
516 fprintf(fp1,"%10g",0.5*(time[i]+time[i-1])-time[0]);
517 for(m=0; (m<=nsets); m++) {
518 fprintf(fp1," %10g",(av[m]-avold[m])/dt);
538 gmx_large_int_t nst_min;
541 static void clear_ee_sum(ee_sum_t *ees)
549 static void add_ee_sum(ee_sum_t *ees,double sum,int np)
555 static void add_ee_av(ee_sum_t *ees)
559 av = ees->sum/ees->np;
566 static double calc_ee2(int nb,ee_sum_t *ees)
568 return (ees->sav2/nb - dsqr(ees->sav/nb))/(nb - 1);
571 static void set_ee_av(ener_ee_t *eee)
575 char buf[STEPSTRSIZE];
576 fprintf(debug,"Storing average for err.est.: %s steps\n",
577 gmx_step_str(eee->nst,buf));
579 add_ee_av(&eee->sum);
581 if (eee->b == 1 || eee->nst < eee->nst_min)
583 eee->nst_min = eee->nst;
588 static void calc_averages(int nset,enerdata_t *edat,int nbmin,int nbmax)
591 double sum,sum2,sump,see2;
592 gmx_large_int_t steps,np,p,bound_nb;
596 double x,sx,sy,sxx,sxy;
599 /* Check if we have exact statistics over all points */
600 for(i=0; i<nset; i++)
603 ed->bExactStat = FALSE;
604 if (edat->npoints > 0)
606 /* All energy file sum entries 0 signals no exact sums.
607 * But if all energy values are 0, we still have exact sums.
610 for(f=0; f<edat->nframes && !ed->bExactStat; f++)
612 if (ed->ener[i] != 0)
616 ed->bExactStat = (ed->es[f].sum != 0);
620 ed->bExactStat = TRUE;
626 for(i=0; i<nset; i++)
637 for(nb=nbmin; nb<=nbmax; nb++)
640 clear_ee_sum(&eee[nb].sum);
644 for(f=0; f<edat->nframes; f++)
650 /* Add the sum and the sum of variances to the totals. */
656 sum2 += dsqr(sum/np - (sum + es->sum)/(np + p))
662 /* Add a single value to the sum and sum of squares. */
668 /* sum has to be increased after sum2 */
672 /* For the linear regression use variance 1/p.
673 * Note that sump is the sum, not the average, so we don't need p*.
675 x = edat->step[f] - 0.5*(edat->steps[f] - 1);
681 for(nb=nbmin; nb<=nbmax; nb++)
683 /* Check if the current end step is closer to the desired
684 * block boundary than the next end step.
686 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
687 if (eee[nb].nst > 0 &&
688 bound_nb - edat->step[f-1]*nb < edat->step[f]*nb - bound_nb)
698 eee[nb].nst += edat->step[f] - edat->step[f-1];
702 add_ee_sum(&eee[nb].sum,es->sum,edat->points[f]);
706 add_ee_sum(&eee[nb].sum,edat->s[i].ener[f],1);
708 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
709 if (edat->step[f]*nb >= bound_nb)
716 edat->s[i].av = sum/np;
719 edat->s[i].rmsd = sqrt(sum2/np);
723 edat->s[i].rmsd = sqrt(sum2/np - dsqr(edat->s[i].av));
726 if (edat->nframes > 1)
728 edat->s[i].slope = (np*sxy - sx*sy)/(np*sxx - sx*sx);
732 edat->s[i].slope = 0;
737 for(nb=nbmin; nb<=nbmax; nb++)
739 /* Check if we actually got nb blocks and if the smallest
740 * block is not shorter than 80% of the average.
744 char buf1[STEPSTRSIZE],buf2[STEPSTRSIZE];
745 fprintf(debug,"Requested %d blocks, we have %d blocks, min %s nsteps %s\n",
747 gmx_step_str(eee[nb].nst_min,buf1),
748 gmx_step_str(edat->nsteps,buf2));
750 if (eee[nb].b == nb && 5*nb*eee[nb].nst_min >= 4*edat->nsteps)
752 see2 += calc_ee2(nb,&eee[nb].sum);
758 edat->s[i].ee = sqrt(see2/nee);
768 static enerdata_t *calc_sum(int nset,enerdata_t *edat,int nbmin,int nbmax)
779 snew(s->ener,esum->nframes);
780 snew(s->es ,esum->nframes);
782 s->bExactStat = TRUE;
784 for(i=0; i<nset; i++)
786 if (!edat->s[i].bExactStat)
788 s->bExactStat = FALSE;
790 s->slope += edat->s[i].slope;
793 for(f=0; f<edat->nframes; f++)
796 for(i=0; i<nset; i++)
798 sum += edat->s[i].ener[f];
802 for(i=0; i<nset; i++)
804 sum += edat->s[i].es[f].sum;
810 calc_averages(1,esum,nbmin,nbmax);
815 static char *ee_pr(double ee,char *buf)
822 sprintf(buf,"%s","--");
826 /* Round to two decimals by printing. */
827 sprintf(tmp,"%.1e",ee);
828 sscanf(tmp,"%lf",&rnd);
829 sprintf(buf,"%g",rnd);
835 static void remove_drift(int nset,int nbmin,int nbmax,real dt,enerdata_t *edat)
837 /* Remove the drift by performing a fit to y = ax+b.
838 Uses 5 iterations. */
840 double delta,d,sd,sd2;
842 edat->npoints = edat->nframes;
843 edat->nsteps = edat->nframes;
847 for(i=0; (i<nset); i++)
849 delta = edat->s[i].slope*dt;
852 fprintf(debug,"slope for set %d is %g\n",i,edat->s[i].slope);
854 for(j=0; (j<edat->nframes); j++)
856 edat->s[i].ener[j] -= j*delta;
857 edat->s[i].es[j].sum = 0;
858 edat->s[i].es[j].sum2 = 0;
861 calc_averages(nset,edat,nbmin,nbmax);
865 static void calc_fluctuation_props(FILE *fp,
866 gmx_bool bDriftCorr,real dt,
867 int nset,int set[],int nmol,
868 char **leg,enerdata_t *edat,
872 double vvhh,vv,v,h,hh2,vv2,varv,hh,varh,tt,cv,cp,alpha,kappa,dcp,et,varet;
874 enum { eVol, eEnth, eTemp, eEtot, eNR };
875 const char *my_ener[] = { "Volume", "Enthalpy", "Temperature", "Total Energy" };
878 NANO3 = NANO*NANO*NANO;
881 fprintf(fp,"\nYou may want to use the -driftcorr flag in order to correct\n"
882 "for spurious drift in the graphs. Note that this is not\n"
883 "a substitute for proper equilibration and sampling!\n");
887 remove_drift(nset,nbmin,nbmax,dt,edat);
889 for(i=0; (i<eNR); i++)
891 for(ii[i]=0; (ii[i]<nset &&
892 (gmx_strcasecmp(leg[ii[i]],my_ener[i]) != 0)); ii[i]++)
895 fprintf(fp,"Found %s data.\n",my_ener[i]);
897 /* Compute it all! */
898 vvhh = alpha = kappa = cp = dcp = cv = NOTSET;
902 if (ii[eTemp] < nset)
904 tt = edat->s[ii[eTemp]].av;
908 if ((ii[eVol] < nset) && (ii[eTemp] < nset))
910 vv = edat->s[ii[eVol]].av*NANO3;
911 varv = dsqr(edat->s[ii[eVol]].rmsd*NANO3);
912 kappa = (varv/vv)/(BOLTZMANN*tt);
916 if ((ii[eEnth] < nset) && (ii[eTemp] < nset))
918 hh = KILO*edat->s[ii[eEnth]].av/AVOGADRO;
919 varh = dsqr(KILO*edat->s[ii[eEnth]].rmsd/AVOGADRO);
920 cp = AVOGADRO*((varh/nmol)/(BOLTZMANN*tt*tt));
924 if ((ii[eEtot] < nset) && (hh == NOTSET) && (tt != NOTSET))
926 /* Only compute cv in constant volume runs, which we can test
927 by checking whether the enthalpy was computed.
929 et = edat->s[ii[eEtot]].av;
930 varet = sqr(edat->s[ii[eEtot]].rmsd);
931 cv = KILO*((varet/nmol)/(BOLTZ*tt*tt));
934 if ((ii[eVol] < nset) && (ii[eEnth] < nset) && (ii[eTemp] < nset))
937 for(j=0; (j<edat->nframes); j++)
939 v = edat->s[ii[eVol]].ener[j]*NANO3;
940 h = KILO*edat->s[ii[eEnth]].ener[j]/AVOGADRO;
943 vvhh /= edat->nframes;
944 alpha = (vvhh-vv*hh)/(vv*BOLTZMANN*tt*tt);
945 dcp = (vv*AVOGADRO/nmol)*tt*sqr(alpha)/(kappa);
951 fprintf(fp,"\nWARNING: nmol = %d, this may not be what you want.\n",
953 fprintf(fp,"\nTemperature dependent fluctuation properties at T = %g.\n",tt);
954 fprintf(fp,"\nHeat capacities obtained from fluctuations do *not* include\n");
955 fprintf(fp,"quantum corrections. If you want to get a more accurate estimate\n");
956 fprintf(fp,"please use the g_dos program.\n\n");
957 fprintf(fp,"WARNING: Please verify that your simulations are converged and perform\n"
958 "a block-averaging error analysis (not implemented in g_energy yet)\n");
963 fprintf(fp,"varv = %10g (m^6)\n",varv*AVOGADRO/nmol);
965 fprintf(fp,"vvhh = %10g (m^3 J)\n",vvhh);
968 fprintf(fp,"Volume = %10g m^3/mol\n",
971 fprintf(fp,"Enthalpy = %10g kJ/mol\n",
972 hh*AVOGADRO/(KILO*nmol));
974 fprintf(fp,"Coefficient of Thermal Expansion Alpha_P = %10g (1/K)\n",
978 fprintf(fp,"Isothermal Compressibility Kappa = %10g (J/m^3)\n",
980 fprintf(fp,"Adiabatic bulk modulus = %10g (m^3/J)\n",
984 fprintf(fp,"Heat capacity at constant pressure Cp = %10g J/mol K\n",
987 fprintf(fp,"Heat capacity at constant volume Cv = %10g J/mol K\n",
990 fprintf(fp,"Cp-Cv = %10g J/mol K\n",
992 please_cite(fp,"Allen1987a");
996 fprintf(fp,"You should select the temperature in order to obtain fluctuation properties.\n");
1000 static void analyse_ener(gmx_bool bCorr,const char *corrfn,
1001 gmx_bool bFee,gmx_bool bSum,gmx_bool bFluct,gmx_bool bTempFluct,
1002 gmx_bool bVisco,const char *visfn,int nmol,
1003 gmx_large_int_t start_step,double start_t,
1004 gmx_large_int_t step,double t,
1005 double time[], real reftemp,
1007 int nset,int set[],gmx_bool *bIsEner,
1008 char **leg,gmx_enxnm_t *enm,
1009 real Vaver,real ezero,
1010 int nbmin,int nbmax,
1011 const output_env_t oenv)
1014 /* Check out the printed manual for equations! */
1015 double Dt,aver,stddev,errest,delta_t,totaldrift;
1016 enerdata_t *esum=NULL;
1017 real xxx,integral,intBulk,Temp=0,Pres=0;
1018 real sfrac,oldfrac,diffsum,diffav,fstep,pr_aver,pr_stddev,pr_errest;
1019 double beta=0,expE,expEtot,*fee=NULL;
1020 gmx_large_int_t nsteps;
1021 int nexact,nnotexact;
1025 char buf[256],eebuf[100];
1027 nsteps = step - start_step + 1;
1029 fprintf(stdout,"Not enough steps (%s) for statistics\n",
1030 gmx_step_str(nsteps,buf));
1033 /* Calculate the time difference */
1034 delta_t = t - start_t;
1036 fprintf(stdout,"\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
1037 gmx_step_str(nsteps,buf),start_t,t,nset);
1039 calc_averages(nset,edat,nbmin,nbmax);
1042 esum = calc_sum(nset,edat,nbmin,nbmax);
1045 if (edat->npoints == 0) {
1051 for(i=0; (i<nset); i++) {
1052 if (edat->s[i].bExactStat) {
1060 if (nnotexact == 0) {
1061 fprintf(stdout,"All statistics are over %s points\n",
1062 gmx_step_str(edat->npoints,buf));
1063 } else if (nexact == 0 || edat->npoints == edat->nframes) {
1064 fprintf(stdout,"All statistics are over %d points (frames)\n",
1067 fprintf(stdout,"The term%s",nnotexact==1 ? "" : "s");
1068 for(i=0; (i<nset); i++) {
1069 if (!edat->s[i].bExactStat) {
1070 fprintf(stdout," '%s'",leg[i]);
1073 fprintf(stdout," %s has statistics over %d points (frames)\n",
1074 nnotexact==1 ? "is" : "are",edat->nframes);
1075 fprintf(stdout,"All other statistics are over %s points\n",
1076 gmx_step_str(edat->npoints,buf));
1078 fprintf(stdout,"\n");
1080 fprintf(stdout,"%-24s %10s %10s %10s %10s",
1081 "Energy","Average","Err.Est.","RMSD","Tot-Drift");
1083 fprintf(stdout," %10s\n","-kT ln<e^(E/kT)>");
1085 fprintf(stdout,"\n");
1086 fprintf(stdout,"-------------------------------------------------------------------------------\n");
1088 /* Initiate locals, only used with -sum */
1091 beta = 1.0/(BOLTZ*reftemp);
1094 for(i=0; (i<nset); i++) {
1095 aver = edat->s[i].av;
1096 stddev = edat->s[i].rmsd;
1097 errest = edat->s[i].ee;
1101 for(j=0; (j<edat->nframes); j++) {
1102 expE += exp(beta*(edat->s[i].ener[j] - aver)/nmol);
1105 expEtot+=expE/edat->nframes;
1107 fee[i] = log(expE/edat->nframes)/beta + aver/nmol;
1109 if (strstr(leg[i],"empera") != NULL) {
1111 } else if (strstr(leg[i],"olum") != NULL) {
1113 } else if (strstr(leg[i],"essure") != NULL) {
1117 pr_aver = aver/nmol-ezero;
1118 pr_stddev = stddev/nmol;
1119 pr_errest = errest/nmol;
1127 /* Multiply the slope in steps with the number of steps taken */
1128 totaldrift = (edat->nsteps - 1)*edat->s[i].slope;
1134 fprintf(stdout,"%-24s %10g %10s %10g %10g",
1135 leg[i],pr_aver,ee_pr(pr_errest,eebuf),pr_stddev,totaldrift);
1137 fprintf(stdout," %10g",fee[i]);
1139 fprintf(stdout," (%s)\n",enm[set[i]].unit);
1142 for(j=0; (j<edat->nframes); j++)
1143 edat->s[i].ener[j] -= aver;
1147 totaldrift = (edat->nsteps - 1)*esum->s[0].slope;
1148 fprintf(stdout,"%-24s %10g %10s %10s %10g (%s)",
1149 "Total",esum->s[0].av/nmol,ee_pr(esum->s[0].ee/nmol,eebuf),
1150 "--",totaldrift/nmol,enm[set[0]].unit);
1151 /* pr_aver,pr_stddev,a,totaldrift */
1153 fprintf(stdout," %10g %10g\n",
1154 log(expEtot)/beta + esum->s[0].av/nmol,log(expEtot)/beta);
1156 fprintf(stdout,"\n");
1159 /* Do correlation function */
1160 if (edat->nframes > 1)
1162 Dt = delta_t/(edat->nframes - 1);
1169 const char* leg[] = { "Shear", "Bulk" };
1174 /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
1176 /* Symmetrise tensor! (and store in first three elements)
1177 * And subtract average pressure!
1180 for(i=0; i<12; i++) {
1181 snew(eneset[i],edat->nframes);
1184 for(i=0; i<3; i++) {
1185 snew(enesum[i],edat->nframes);
1187 for(i=0; (i<edat->nframes); i++) {
1188 eneset[0][i] = 0.5*(edat->s[1].ener[i]+edat->s[3].ener[i]);
1189 eneset[1][i] = 0.5*(edat->s[2].ener[i]+edat->s[6].ener[i]);
1190 eneset[2][i] = 0.5*(edat->s[5].ener[i]+edat->s[7].ener[i]);
1191 for(j=3; j<=11; j++) {
1192 eneset[j][i] = edat->s[j].ener[i];
1194 eneset[11][i] -= Pres;
1195 enesum[0][i] = 0.5*(edat->s[1].es[i].sum+edat->s[3].es[i].sum);
1196 enesum[1][i] = 0.5*(edat->s[2].es[i].sum+edat->s[6].es[i].sum);
1197 enesum[2][i] = 0.5*(edat->s[5].es[i].sum+edat->s[7].es[i].sum);
1200 einstein_visco("evisco.xvg","eviscoi.xvg",
1201 3,edat->nframes,enesum,Vaver,Temp,nsteps,time,oenv);
1203 /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
1204 /* Do it for shear viscosity */
1205 strcpy(buf,"Shear Viscosity");
1206 low_do_autocorr(corrfn,oenv,buf,edat->nframes,3,
1207 (edat->nframes+1)/2,eneset,Dt,
1208 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1210 /* Now for bulk viscosity */
1211 strcpy(buf,"Bulk Viscosity");
1212 low_do_autocorr(corrfn,oenv,buf,edat->nframes,1,
1213 (edat->nframes+1)/2,&(eneset[11]),Dt,
1214 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1216 factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
1217 fp=xvgropen(visfn,buf,"Time (ps)","\\8h\\4 (cp)",oenv);
1218 xvgr_legend(fp,asize(leg),leg,oenv);
1220 /* Use trapezium rule for integration */
1223 nout = get_acfnout();
1224 if ((nout < 2) || (nout >= edat->nframes/2))
1225 nout = edat->nframes/2;
1226 for(i=1; (i<nout); i++)
1228 integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
1229 intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
1230 fprintf(fp,"%10g %10g %10g\n",(i*Dt),integral,intBulk);
1236 strcpy(buf,"Autocorrelation of Energy Fluctuations");
1238 strcpy(buf,"Energy Autocorrelation");
1240 do_autocorr(corrfn,oenv,buf,edat->nframes,
1242 bSum ? &edat->s[nset-1].ener : eneset,
1243 (delta_t/edat->nframes),eacNormal,FALSE);
1249 static void print_time(FILE *fp,double t)
1251 fprintf(fp,"%12.6f",t);
1254 static void print1(FILE *fp,gmx_bool bDp,real e)
1257 fprintf(fp," %16.12f",e);
1259 fprintf(fp," %10.6f",e);
1262 static void fec(const char *ene2fn, const char *runavgfn,
1263 real reftemp, int nset, int set[], char *leg[],
1264 enerdata_t *edat, double time[],
1265 const output_env_t oenv)
1267 const char* ravgleg[] = { "\\8D\\4E = E\\sB\\N-E\\sA\\N",
1268 "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N" };
1271 int nre,timecheck,step,nenergy,nenergy2,maxenergy;
1277 gmx_enxnm_t *enm=NULL;
1281 /* read second energy file */
1284 enx = open_enx(ene2fn,"r");
1285 do_enxnms(enx,&(fr->nre),&enm);
1287 snew(eneset2,nset+1);
1292 /* This loop searches for the first frame (when -b option is given),
1293 * or when this has been found it reads just one energy frame
1296 bCont = do_enx(enx,fr);
1299 timecheck = check_times(fr->t);
1301 } while (bCont && (timecheck < 0));
1303 /* Store energies for analysis afterwards... */
1304 if ((timecheck == 0) && bCont) {
1306 if ( nenergy2 >= maxenergy ) {
1308 for(i=0; i<=nset; i++)
1309 srenew(eneset2[i],maxenergy);
1311 if (fr->t != time[nenergy2])
1312 fprintf(stderr,"\nWARNING time mismatch %g!=%g at frame %s\n",
1313 fr->t, time[nenergy2], gmx_step_str(fr->step,buf));
1314 for(i=0; i<nset; i++)
1315 eneset2[i][nenergy2] = fr->ener[set[i]].e;
1319 } while (bCont && (timecheck == 0));
1322 if (edat->nframes != nenergy2) {
1323 fprintf(stderr,"\nWARNING file length mismatch %d!=%d\n",
1324 edat->nframes,nenergy2);
1326 nenergy = min(edat->nframes,nenergy2);
1328 /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
1331 fp=xvgropen(runavgfn,"Running average free energy difference",
1332 "Time (" unit_time ")","\\8D\\4E (" unit_energy ")",oenv);
1333 xvgr_legend(fp,asize(ravgleg),ravgleg,oenv);
1335 fprintf(stdout,"\n%-24s %10s\n",
1336 "Energy","dF = -kT ln < exp(-(EB-EA)/kT) >A");
1338 beta = 1.0/(BOLTZ*reftemp);
1339 for(i=0; i<nset; i++) {
1340 if (gmx_strcasecmp(leg[i],enm[set[i]].name)!=0)
1341 fprintf(stderr,"\nWARNING energy set name mismatch %s!=%s\n",
1342 leg[i],enm[set[i]].name);
1343 for(j=0; j<nenergy; j++) {
1344 dE = eneset2[i][j] - edat->s[i].ener[j];
1345 sum += exp(-dE*beta);
1347 fprintf(fp,"%10g %10g %10g\n",
1348 time[j], dE, -BOLTZ*reftemp*log(sum/(j+1)) );
1350 aver = -BOLTZ*reftemp*log(sum/nenergy);
1351 fprintf(stdout,"%-24s %10g\n",leg[i],aver);
1358 static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
1359 int *blocks, int *hists, int *samples, int *nlambdas,
1360 const output_env_t oenv)
1362 const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
1363 char title[STRLEN],label_x[STRLEN],label_y[STRLEN], legend[STRLEN];
1365 gmx_bool first=FALSE;
1366 int nblock_hist=0, nblock_dh=0, nblock_dhcoll=0;
1369 double temp=0, start_time=0, delta_time=0, start_lambda=0, delta_lambda=0;
1371 gmx_bool changing_lambda=FALSE;
1373 /* now count the blocks & handle the global dh data */
1374 for(i=0;i<fr->nblock;i++)
1376 if (fr->block[i].id == enxDHHIST)
1380 else if (fr->block[i].id == enxDH)
1384 else if (fr->block[i].id == enxDHCOLL)
1387 if ( (fr->block[i].nsub < 1) ||
1388 (fr->block[i].sub[0].type != xdr_datatype_double) ||
1389 (fr->block[i].sub[0].nr < 5))
1391 gmx_fatal(FARGS, "Unexpected block data");
1394 /* read the data from the DHCOLL block */
1395 temp = fr->block[i].sub[0].dval[0];
1396 start_time = fr->block[i].sub[0].dval[1];
1397 delta_time = fr->block[i].sub[0].dval[2];
1398 start_lambda = fr->block[i].sub[0].dval[3];
1399 delta_lambda = fr->block[i].sub[0].dval[4];
1400 changing_lambda = (delta_lambda != 0);
1404 if (nblock_hist == 0 && nblock_dh == 0)
1406 /* don't do anything */
1409 if (nblock_hist>0 && nblock_dh>0)
1411 gmx_fatal(FARGS, "This energy file contains both histogram dhdl data and non-histogram dhdl data. Don't know what to do.");
1417 sprintf(title,"%s, %s",dhdl,deltag);
1418 sprintf(label_x,"%s (%s)","Time",unit_time);
1419 sprintf(label_y,"(%s)",unit_energy);
1423 sprintf(title,"N(%s)",deltag);
1424 sprintf(label_x,"%s (%s)",deltag,unit_energy);
1425 sprintf(label_y,"Samples");
1427 *fp_dhdl=xvgropen_type(filename, title, label_x, label_y, exvggtXNY,
1429 if (! changing_lambda)
1431 sprintf(buf,"T = %g (K), %s = %g", temp, lambda, start_lambda);
1435 sprintf(buf,"T = %g (K)", temp);
1437 xvgr_subtitle(*fp_dhdl,buf,oenv);
1443 (*hists)+=nblock_hist;
1444 (*blocks)+=nblock_dh;
1445 (*nlambdas) = nblock_hist+nblock_dh;
1448 /* write the data */
1449 if (nblock_hist > 0)
1451 gmx_large_int_t sum=0;
1453 for(i=0;i<fr->nblock;i++)
1455 t_enxblock *blk=&(fr->block[i]);
1456 if (blk->id==enxDHHIST)
1458 double foreign_lambda, dx;
1460 int nhist, derivative;
1462 /* check the block types etc. */
1463 if ( (blk->nsub < 2) ||
1464 (blk->sub[0].type != xdr_datatype_double) ||
1465 (blk->sub[1].type != xdr_datatype_large_int) ||
1466 (blk->sub[0].nr < 2) ||
1467 (blk->sub[1].nr < 2) )
1469 gmx_fatal(FARGS, "Unexpected block data in file");
1471 foreign_lambda=blk->sub[0].dval[0];
1472 dx=blk->sub[0].dval[1];
1473 nhist=blk->sub[1].lval[0];
1474 derivative=blk->sub[1].lval[1];
1475 for(j=0;j<nhist;j++)
1478 x0=blk->sub[1].lval[2+j];
1482 sprintf(legend, "N(%s(%s=%g) | %s=%g)",
1483 deltag, lambda, foreign_lambda,
1484 lambda, start_lambda);
1488 sprintf(legend, "N(%s | %s=%g)",
1489 dhdl, lambda, start_lambda);
1493 xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv);
1495 for(k=0;k<blk->sub[j+2].nr;k++)
1500 hist=blk->sub[j+2].ival[k];
1503 fprintf(*fp_dhdl,"%g %d\n%g %d\n", xmin, hist,
1507 /* multiple histogram data blocks in one histogram
1508 mean that the second one is the reverse of the first one:
1509 for dhdl derivatives, it's important to know both the
1510 maximum and minimum values */
1516 (*samples) += (int)(sum/nblock_hist);
1522 char **setnames=NULL;
1523 int nnames=nblock_dh;
1525 if (changing_lambda)
1531 snew(setnames, nnames);
1535 if ( changing_lambda && first)
1537 /* lambda is a plotted value */
1538 setnames[j]=gmx_strdup(lambda);
1543 for(i=0;i<fr->nblock;i++)
1545 t_enxblock *blk=&(fr->block[i]);
1546 if (blk->id == enxDH)
1550 /* do the legends */
1552 double foreign_lambda;
1554 derivative=blk->sub[0].ival[0];
1555 foreign_lambda=blk->sub[1].dval[0];
1559 sprintf(buf, "%s %s %g",dhdl,lambda,start_lambda);
1563 sprintf(buf, "%s %s %g",deltag,lambda, foreign_lambda);
1565 setnames[j] = gmx_strdup(buf);
1575 if (len!=blk->sub[2].nr)
1577 gmx_fatal(FARGS, "Length inconsistency in dhdl data");
1586 xvgr_legend(*fp_dhdl, nblock_dh, (const char**)setnames, oenv);
1588 for(i=0;i<nblock_dh;i++)
1598 double time=start_time + delta_time*i;
1600 fprintf(*fp_dhdl,"%.4f", time);
1601 if (fabs(delta_lambda) > 1e-9)
1603 double lambda_now=i*delta_lambda + start_lambda;
1604 fprintf(*fp_dhdl," %.4f", lambda_now);
1606 for(j=0;j<fr->nblock;j++)
1608 t_enxblock *blk=&(fr->block[j]);
1609 if (blk->id == enxDH)
1612 if (blk->sub[2].type == xdr_datatype_float)
1614 value=blk->sub[2].fval[i];
1618 value=blk->sub[2].dval[i];
1620 fprintf(*fp_dhdl," %g", value);
1623 fprintf(*fp_dhdl, "\n");
1629 int gmx_energy(int argc,char *argv[])
1631 const char *desc[] = {
1633 "[TT]g_energy[tt] extracts energy components or distance restraint",
1634 "data from an energy file. The user is prompted to interactively",
1635 "select the desired energy terms.[PAR]",
1637 "Average, RMSD, and drift are calculated with full precision from the",
1638 "simulation (see printed manual). Drift is calculated by performing",
1639 "a least-squares fit of the data to a straight line. The reported total drift",
1640 "is the difference of the fit at the first and last point.",
1641 "An error estimate of the average is given based on a block averages",
1642 "over 5 blocks using the full-precision averages. The error estimate",
1643 "can be performed over multiple block lengths with the options",
1644 "[TT]-nbmin[tt] and [TT]-nbmax[tt].",
1645 "[BB]Note[bb] that in most cases the energy files contains averages over all",
1646 "MD steps, or over many more points than the number of frames in",
1647 "energy file. This makes the [TT]g_energy[tt] statistics output more accurate",
1648 "than the [TT].xvg[tt] output. When exact averages are not present in the energy",
1649 "file, the statistics mentioned above are simply over the single, per-frame",
1650 "energy values.[PAR]",
1652 "The term fluctuation gives the RMSD around the least-squares fit.[PAR]",
1654 "Some fluctuation-dependent properties can be calculated provided",
1655 "the correct energy terms are selected. The following properties",
1656 "will be computed:[BR]",
1657 "Property Energy terms needed[BR]",
1658 "---------------------------------------------------[BR]",
1659 "Heat capacity C[SUB]p[sub] (NPT sims): Enthalpy, Temp [BR]",
1660 "Heat capacity C[SUB]v[sub] (NVT sims): Etot, Temp [BR]",
1661 "Thermal expansion coeff. (NPT): Enthalpy, Vol, Temp[BR]",
1662 "Isothermal compressibility: Vol, Temp [BR]",
1663 "Adiabatic bulk modulus: Vol, Temp [BR]",
1664 "---------------------------------------------------[BR]",
1665 "You always need to set the number of molecules [TT]-nmol[tt].",
1666 "The C[SUB]p[sub]/C[SUB]v[sub] computations do [BB]not[bb] include any corrections",
1667 "for quantum effects. Use the [TT]g_dos[tt] program if you need that (and you do).[PAR]"
1668 "When the [TT]-viol[tt] option is set, the time averaged",
1669 "violations are plotted and the running time-averaged and",
1670 "instantaneous sum of violations are recalculated. Additionally",
1671 "running time-averaged and instantaneous distances between",
1672 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
1674 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
1675 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
1676 "The first two options plot the orientation, the last three the",
1677 "deviations of the orientations from the experimental values.",
1678 "The options that end on an 'a' plot the average over time",
1679 "as a function of restraint. The options that end on a 't'",
1680 "prompt the user for restraint label numbers and plot the data",
1681 "as a function of time. Option [TT]-odr[tt] plots the RMS",
1682 "deviation as a function of restraint.",
1683 "When the run used time or ensemble averaged orientation restraints,",
1684 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
1685 "not ensemble-averaged orientations and deviations instead of",
1686 "the time and ensemble averages.[PAR]",
1688 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
1689 "tensor for each orientation restraint experiment. With option",
1690 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
1692 "Option [TT]-odh[tt] extracts and plots the free energy data",
1693 "(Hamiltoian differences and/or the Hamiltonian derivative dhdl)",
1694 "from the [TT]ener.edr[tt] file.[PAR]",
1696 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
1697 "difference with an ideal gas state: [BR]",
1698 " [GRK]Delta[grk] A = A(N,V,T) - A[SUB]idealgas[sub](N,V,T) = kT [LN][CHEVRON][EXP]U[SUB]pot[sub]/kT[exp][chevron][ln][BR]",
1699 " [GRK]Delta[grk] G = G(N,p,T) - G[SUB]idealgas[sub](N,p,T) = kT [LN][CHEVRON][EXP]U[SUB]pot[sub]/kT[exp][chevron][ln][BR]",
1700 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
1701 "the average is over the ensemble (or time in a trajectory).",
1702 "Note that this is in principle",
1703 "only correct when averaging over the whole (Boltzmann) ensemble",
1704 "and using the potential energy. This also allows for an entropy",
1705 "estimate using:[BR]",
1706 " [GRK]Delta[grk] S(N,V,T) = S(N,V,T) - S[SUB]idealgas[sub](N,V,T) = ([CHEVRON]U[SUB]pot[sub][chevron] - [GRK]Delta[grk] A)/T[BR]",
1707 " [GRK]Delta[grk] S(N,p,T) = S(N,p,T) - S[SUB]idealgas[sub](N,p,T) = ([CHEVRON]U[SUB]pot[sub][chevron] + pV - [GRK]Delta[grk] G)/T",
1710 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
1711 "difference is calculated [BR] dF = -kT [LN][CHEVRON][EXP]-(E[SUB]B[sub]-E[SUB]A[sub])/kT[exp][chevron][SUB]A[sub][ln] ,",
1712 "where E[SUB]A[sub] and E[SUB]B[sub] are the energies from the first and second energy",
1713 "files, and the average is over the ensemble A. The running average",
1714 "of the free energy difference is printed to a file specified by [TT]-ravg[tt].",
1715 "[BB]Note[bb] that the energies must both be calculated from the same trajectory."
1718 static gmx_bool bSum=FALSE,bFee=FALSE,bPrAll=FALSE,bFluct=FALSE,bDriftCorr=FALSE;
1719 static gmx_bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE;
1720 static int skip=0,nmol=1,nbmin=5,nbmax=5;
1721 static real reftemp=300.0,ezero=0;
1723 { "-fee", FALSE, etBOOL, {&bFee},
1724 "Do a free energy estimate" },
1725 { "-fetemp", FALSE, etREAL,{&reftemp},
1726 "Reference temperature for free energy calculation" },
1727 { "-zero", FALSE, etREAL, {&ezero},
1728 "Subtract a zero-point energy" },
1729 { "-sum", FALSE, etBOOL, {&bSum},
1730 "Sum the energy terms selected rather than display them all" },
1731 { "-dp", FALSE, etBOOL, {&bDp},
1732 "Print energies in high precision" },
1733 { "-nbmin", FALSE, etINT, {&nbmin},
1734 "Minimum number of blocks for error estimate" },
1735 { "-nbmax", FALSE, etINT, {&nbmax},
1736 "Maximum number of blocks for error estimate" },
1737 { "-mutot",FALSE, etBOOL, {&bMutot},
1738 "Compute the total dipole moment from the components" },
1739 { "-skip", FALSE, etINT, {&skip},
1740 "Skip number of frames between data points" },
1741 { "-aver", FALSE, etBOOL, {&bPrAll},
1742 "Also print the exact average and rmsd stored in the energy frames (only when 1 term is requested)" },
1743 { "-nmol", FALSE, etINT, {&nmol},
1744 "Number of molecules in your sample: the energies are divided by this number" },
1745 { "-driftcorr", FALSE, etBOOL, {&bDriftCorr},
1746 "Useful only for calculations of fluctuation properties. The drift in the observables will be subtracted before computing the fluctuation properties."},
1747 { "-fluc", FALSE, etBOOL, {&bFluct},
1748 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
1749 { "-orinst", FALSE, etBOOL, {&bOrinst},
1750 "Analyse instantaneous orientation data" },
1751 { "-ovec", FALSE, etBOOL, {&bOvec},
1752 "Also plot the eigenvectors with [TT]-oten[tt]" }
1754 const char* drleg[] = {
1758 static const char *setnm[] = {
1759 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
1760 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
1761 "Volume", "Pressure"
1764 FILE *out=NULL,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
1770 gmx_localtop_t *top=NULL;
1774 gmx_enxnm_t *enm=NULL;
1775 t_enxframe *frame,*fr=NULL;
1777 #define NEXT (1-cur)
1778 int nre,teller,teller_disre,nfr;
1779 gmx_large_int_t start_step;
1780 int nor=0,nex=0,norfr=0,enx_i=0;
1782 real *bounds=NULL,*violaver=NULL,*oobs=NULL,*orient=NULL,*odrms=NULL;
1783 int *index=NULL,*pair=NULL,norsel=0,*orsel=NULL,*or_label=NULL;
1784 int nbounds=0,npairs;
1785 gmx_bool bDisRe,bDRAll,bORA,bORT,bODA,bODR,bODT,bORIRE,bOTEN,bDHDL;
1786 gmx_bool bFoundStart,bCont,bEDR,bVisco;
1787 double sum,sumaver,sumt,ener,dbl;
1790 int *set=NULL,i,j,k,nset,sss;
1791 gmx_bool *bIsEner=NULL;
1792 char **pairleg,**odtleg,**otenleg;
1795 char *anm_j,*anm_k,*resnm_j,*resnm_k;
1796 int resnr_j,resnr_k;
1797 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
1800 t_enxblock *blk=NULL;
1801 t_enxblock *blk_disre=NULL;
1803 int dh_blocks=0, dh_hists=0, dh_samples=0, dh_lambdas=0;
1806 { efEDR, "-f", NULL, ffREAD },
1807 { efEDR, "-f2", NULL, ffOPTRD },
1808 { efTPX, "-s", NULL, ffOPTRD },
1809 { efXVG, "-o", "energy", ffWRITE },
1810 { efXVG, "-viol", "violaver",ffOPTWR },
1811 { efXVG, "-pairs","pairs", ffOPTWR },
1812 { efXVG, "-ora", "orienta", ffOPTWR },
1813 { efXVG, "-ort", "orientt", ffOPTWR },
1814 { efXVG, "-oda", "orideva", ffOPTWR },
1815 { efXVG, "-odr", "oridevr", ffOPTWR },
1816 { efXVG, "-odt", "oridevt", ffOPTWR },
1817 { efXVG, "-oten", "oriten", ffOPTWR },
1818 { efXVG, "-corr", "enecorr", ffOPTWR },
1819 { efXVG, "-vis", "visco", ffOPTWR },
1820 { efXVG, "-ravg", "runavgdf",ffOPTWR },
1821 { efXVG, "-odh", "dhdl" ,ffOPTWR }
1823 #define NFILE asize(fnm)
1827 CopyRight(stderr,argv[0]);
1829 ppa = add_acf_pargs(&npargs,pa);
1830 parse_common_args(&argc,argv,
1831 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
1832 NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
1834 bDRAll = opt2bSet("-pairs",NFILE,fnm);
1835 bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
1836 bORA = opt2bSet("-ora",NFILE,fnm);
1837 bORT = opt2bSet("-ort",NFILE,fnm);
1838 bODA = opt2bSet("-oda",NFILE,fnm);
1839 bODR = opt2bSet("-odr",NFILE,fnm);
1840 bODT = opt2bSet("-odt",NFILE,fnm);
1841 bORIRE = bORA || bORT || bODA || bODR || bODT;
1842 bOTEN = opt2bSet("-oten",NFILE,fnm);
1843 bDHDL = opt2bSet("-odh",NFILE,fnm);
1848 fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
1849 do_enxnms(fp,&nre,&enm);
1853 bVisco = opt2bSet("-vis",NFILE,fnm);
1855 if (!bDisRe && !bDHDL)
1860 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
1861 for(j=0; j<nset; j++) {
1862 for(i=0; i<nre; i++) {
1863 if (strstr(enm[i].name,setnm[j])) {
1869 if (gmx_strcasecmp(setnm[j],"Volume")==0) {
1870 printf("Enter the box volume (" unit_volume "): ");
1871 if(1 != scanf("%lf",&dbl))
1873 gmx_fatal(FARGS,"Error reading user input");
1877 gmx_fatal(FARGS,"Could not find term %s for viscosity calculation",
1884 set=select_by_name(nre,enm,&nset);
1886 /* Print all the different units once */
1887 sprintf(buf,"(%s)",enm[set[0]].unit);
1888 for(i=1; i<nset; i++) {
1889 for(j=0; j<i; j++) {
1890 if (strcmp(enm[set[i]].unit,enm[set[j]].unit) == 0) {
1896 strcat(buf,enm[set[i]].unit);
1900 out=xvgropen(opt2fn("-o",NFILE,fnm),"Gromacs Energies","Time (ps)",buf,
1904 for(i=0; (i<nset); i++)
1905 leg[i] = enm[set[i]].name;
1907 leg[nset]=strdup("Sum");
1908 xvgr_legend(out,nset+1,(const char**)leg,oenv);
1911 xvgr_legend(out,nset,(const char**)leg,oenv);
1914 for(i=0; (i<nset); i++) {
1916 for (j=0; (j <= F_ETOT); j++)
1917 bIsEner[i] = bIsEner[i] ||
1918 (gmx_strcasecmp(interaction_function[j].longname,leg[i]) == 0);
1921 if (bPrAll && nset > 1) {
1922 gmx_fatal(FARGS,"Printing averages can only be done when a single set is selected");
1927 if (bORIRE || bOTEN)
1928 get_orires_parms(ftp2fn(efTPX,NFILE,fnm),&nor,&nex,&or_label,&oobs);
1941 fprintf(stderr,"Select the orientation restraint labels you want (-1 is all)\n");
1942 fprintf(stderr,"End your selection with 0\n");
1948 if(1 != scanf("%d",&(orsel[j])))
1950 gmx_fatal(FARGS,"Error reading user input");
1952 } while (orsel[j] > 0);
1953 if (orsel[0] == -1) {
1954 fprintf(stderr,"Selecting all %d orientation restraints\n",nor);
1957 for(i=0; i<nor; i++)
1960 /* Build the selection */
1962 for(i=0; i<j; i++) {
1963 for(k=0; k<nor; k++)
1964 if (or_label[k] == orsel[i]) {
1970 fprintf(stderr,"Orientation restraint label %d not found\n",
1974 snew(odtleg,norsel);
1975 for(i=0; i<norsel; i++) {
1976 snew(odtleg[i],256);
1977 sprintf(odtleg[i],"%d",or_label[orsel[i]]);
1980 fort=xvgropen(opt2fn("-ort",NFILE,fnm), "Calculated orientations",
1981 "Time (ps)","",oenv);
1983 fprintf(fort,"%s",orinst_sub);
1984 xvgr_legend(fort,norsel,(const char**)odtleg,oenv);
1987 fodt=xvgropen(opt2fn("-odt",NFILE,fnm),
1988 "Orientation restraint deviation",
1989 "Time (ps)","",oenv);
1991 fprintf(fodt,"%s",orinst_sub);
1992 xvgr_legend(fodt,norsel,(const char**)odtleg,oenv);
1997 foten=xvgropen(opt2fn("-oten",NFILE,fnm),
1998 "Order tensor","Time (ps)","",oenv);
1999 snew(otenleg,bOvec ? nex*12 : nex*3);
2000 for(i=0; i<nex; i++) {
2001 for(j=0; j<3; j++) {
2002 sprintf(buf,"eig%d",j+1);
2003 otenleg[(bOvec ? 12 : 3)*i+j] = strdup(buf);
2006 for(j=0; j<9; j++) {
2007 sprintf(buf,"vec%d%s",j/3+1,j%3==0 ? "x" : (j%3==1 ? "y" : "z"));
2008 otenleg[12*i+3+j] = strdup(buf);
2012 xvgr_legend(foten,bOvec ? nex*12 : nex*3,(const char**)otenleg,oenv);
2017 nbounds=get_bounds(ftp2fn(efTPX,NFILE,fnm),&bounds,&index,&pair,&npairs,
2019 snew(violaver,npairs);
2020 out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
2021 "Time (ps)","nm",oenv);
2022 xvgr_legend(out,2,drleg,oenv);
2024 fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
2025 "Time (ps)","Distance (nm)",oenv);
2026 if (output_env_get_print_xvgr_codes(oenv))
2027 fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
2033 /* Initiate energies and set them to zero */
2042 /* Initiate counters */
2045 bFoundStart = FALSE;
2049 /* This loop searches for the first frame (when -b option is given),
2050 * or when this has been found it reads just one energy frame
2053 bCont = do_enx(fp,&(frame[NEXT]));
2056 timecheck = check_times(frame[NEXT].t);
2058 } while (bCont && (timecheck < 0));
2060 if ((timecheck == 0) && bCont) {
2061 /* We read a valid frame, so we can use it */
2062 fr = &(frame[NEXT]);
2065 /* The frame contains energies, so update cur */
2068 if (edat.nframes % 1000 == 0)
2070 srenew(edat.step,edat.nframes+1000);
2071 memset(&(edat.step[edat.nframes]),0,1000*sizeof(edat.step[0]));
2072 srenew(edat.steps,edat.nframes+1000);
2073 memset(&(edat.steps[edat.nframes]),0,1000*sizeof(edat.steps[0]));
2074 srenew(edat.points,edat.nframes+1000);
2075 memset(&(edat.points[edat.nframes]),0,1000*sizeof(edat.points[0]));
2076 for(i=0; i<nset; i++)
2078 srenew(edat.s[i].ener,edat.nframes+1000);
2079 memset(&(edat.s[i].ener[edat.nframes]),0,
2080 1000*sizeof(edat.s[i].ener[0]));
2082 srenew(edat.s[i].es ,edat.nframes+1000);
2083 memset(&(edat.s[i].es[edat.nframes]),0,
2084 1000*sizeof(edat.s[i].es[0]));
2089 edat.step[nfr] = fr->step;
2094 /* Initiate the previous step data */
2095 start_step = fr->step;
2097 /* Initiate the energy sums */
2098 edat.steps[nfr] = 1;
2099 edat.points[nfr] = 1;
2100 for(i=0; i<nset; i++)
2103 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2104 edat.s[i].es[nfr].sum2 = 0;
2111 edat.steps[nfr] = fr->nsteps;
2113 if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
2117 edat.points[nfr] = 1;
2118 for(i=0; i<nset; i++)
2121 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2122 edat.s[i].es[nfr].sum2 = 0;
2128 edat.points[nfr] = fr->nsum;
2129 for(i=0; i<nset; i++)
2132 edat.s[i].es[nfr].sum = fr->ener[sss].esum;
2133 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
2135 edat.npoints += fr->nsum;
2140 /* The interval does not match fr->nsteps:
2141 * can not do exact averages.
2145 edat.nsteps = fr->step - start_step + 1;
2148 for(i=0; i<nset; i++)
2150 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
2154 * Define distance restraint legends. Can only be done after
2155 * the first frame has been read... (Then we know how many there are)
2157 blk_disre=find_block_id_enxframe(fr, enxDISRE, NULL);
2158 if (bDisRe && bDRAll && !leg && blk_disre)
2163 fa = top->idef.il[F_DISRES].iatoms;
2164 ip = top->idef.iparams;
2165 if (blk_disre->nsub != 2 ||
2166 (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
2168 gmx_incons("Number of disre sub-blocks not equal to 2");
2171 ndisre=blk_disre->sub[0].nr ;
2172 if (ndisre != top->idef.il[F_DISRES].nr/3)
2174 gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
2175 ndisre,top->idef.il[F_DISRES].nr/3);
2177 snew(pairleg,ndisre);
2178 for(i=0; i<ndisre; i++)
2180 snew(pairleg[i],30);
2183 gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
2184 gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
2185 sprintf(pairleg[i],"%d %s %d %s (%d)",
2186 resnr_j,anm_j,resnr_k,anm_k,
2187 ip[fa[3*i]].disres.label);
2189 set=select_it(ndisre,pairleg,&nset);
2191 for(i=0; (i<nset); i++)
2194 sprintf(leg[2*i], "a %s",pairleg[set[i]]);
2195 snew(leg[2*i+1],32);
2196 sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
2198 xvgr_legend(fp_pairs,2*nset,(const char**)leg,oenv);
2202 * Store energies for analysis afterwards...
2204 if (!bDisRe && !bDHDL && (fr->nre > 0)) {
2205 if (edat.nframes % 1000 == 0) {
2206 srenew(time,edat.nframes+1000);
2208 time[edat.nframes] = fr->t;
2212 * Printing time, only when we do not want to skip frames
2214 if (!skip || teller % skip == 0) {
2216 /*******************************************
2217 * D I S T A N C E R E S T R A I N T S
2218 *******************************************/
2222 float *disre_rt = blk_disre->sub[0].fval;
2223 float *disre_rm3tav = blk_disre->sub[1].fval;
2225 double *disre_rt = blk_disre->sub[0].dval;
2226 double *disre_rm3tav = blk_disre->sub[1].dval;
2229 print_time(out,fr->t);
2230 if (violaver == NULL)
2231 snew(violaver,ndisre);
2233 /* Subtract bounds from distances, to calculate violations */
2234 calc_violations(disre_rt, disre_rm3tav,
2235 nbounds,pair,bounds,violaver,&sumt,&sumaver);
2237 fprintf(out," %8.4f %8.4f\n",sumaver,sumt);
2239 print_time(fp_pairs,fr->t);
2240 for(i=0; (i<nset); i++) {
2242 fprintf(fp_pairs," %8.4f", mypow(disre_rm3tav[sss],minthird));
2243 fprintf(fp_pairs," %8.4f", disre_rt[sss]);
2245 fprintf(fp_pairs,"\n");
2252 do_dhdl(fr, &fp_dhdl, opt2fn("-odh",NFILE,fnm),
2253 &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas,
2256 /*******************************************
2258 *******************************************/
2263 /* We skip frames with single points (usually only the first frame),
2264 * since they would result in an average plot with outliers.
2267 print_time(out,fr->t);
2268 print1(out,bDp,fr->ener[set[0]].e);
2269 print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
2270 print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
2276 print_time(out,fr->t);
2280 for(i=0; i<nset; i++)
2282 sum += fr->ener[set[i]].e;
2284 print1(out,bDp,sum/nmol-ezero);
2288 for(i=0; (i<nset); i++)
2292 print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
2296 print1(out,bDp,fr->ener[set[i]].e);
2304 /* we first count the blocks that have id 0: the orire blocks */
2306 for(b=0;b<fr->nblock;b++)
2308 if (fr->block[b].id == mde_block_type_orire)
2312 blk = find_block_id_enxframe(fr, enx_i, NULL);
2316 xdr_datatype dt=xdr_datatype_float;
2318 xdr_datatype dt=xdr_datatype_double;
2322 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2324 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2327 vals=blk->sub[0].fval;
2329 vals=blk->sub[0].dval;
2332 if (blk->sub[0].nr != (size_t)nor)
2333 gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)", blk->sub[0].nr);
2336 for(i=0; i<nor; i++)
2337 orient[i] += vals[i];
2341 for(i=0; i<nor; i++)
2342 odrms[i] += sqr(vals[i]-oobs[i]);
2346 fprintf(fort," %10f",fr->t);
2347 for(i=0; i<norsel; i++)
2348 fprintf(fort," %g",vals[orsel[i]]);
2353 fprintf(fodt," %10f",fr->t);
2354 for(i=0; i<norsel; i++)
2355 fprintf(fodt," %g", vals[orsel[i]]-oobs[orsel[i]]);
2360 blk = find_block_id_enxframe(fr, enxORT, NULL);
2364 xdr_datatype dt=xdr_datatype_float;
2366 xdr_datatype dt=xdr_datatype_double;
2370 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2371 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2373 vals=blk->sub[0].fval;
2375 vals=blk->sub[0].dval;
2378 if (blk->sub[0].nr != (size_t)(nex*12))
2379 gmx_fatal(FARGS,"Number of orientation experiments in energy file (%g) does not match with the topology (%d)",
2380 blk->sub[0].nr/12, nex);
2381 fprintf(foten," %10f",fr->t);
2382 for(i=0; i<nex; i++)
2383 for(j=0; j<(bOvec?12:3); j++)
2384 fprintf(foten," %g",vals[i*12+j]);
2385 fprintf(foten,"\n");
2391 } while (bCont && (timecheck == 0));
2393 fprintf(stderr,"\n");
2407 out = xvgropen(opt2fn("-ora",NFILE,fnm),
2408 "Average calculated orientations",
2409 "Restraint label","",oenv);
2411 fprintf(out,"%s",orinst_sub);
2412 for(i=0; i<nor; i++)
2413 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr);
2417 out = xvgropen(opt2fn("-oda",NFILE,fnm),
2418 "Average restraint deviation",
2419 "Restraint label","",oenv);
2421 fprintf(out,"%s",orinst_sub);
2422 for(i=0; i<nor; i++)
2423 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr-oobs[i]);
2427 out = xvgropen(opt2fn("-odr",NFILE,fnm),
2428 "RMS orientation restraint deviations",
2429 "Restraint label","",oenv);
2431 fprintf(out,"%s",orinst_sub);
2432 for(i=0; i<nor; i++)
2433 fprintf(out,"%5d %g\n",or_label[i],sqrt(odrms[i]/norfr));
2441 analyse_disre(opt2fn("-viol",NFILE,fnm),
2442 teller_disre,violaver,bounds,index,pair,nbounds,oenv);
2449 printf("\n\nWrote %d lambda values with %d samples as ",
2450 dh_lambdas, dh_samples);
2453 printf("%d dH histograms ", dh_hists);
2457 printf("%d dH data blocks ", dh_blocks);
2459 printf("to %s\n", opt2fn("-odh",NFILE,fnm));
2464 gmx_fatal(FARGS, "No dH data in %s\n", opt2fn("-f",NFILE,fnm));
2470 double dt = (frame[cur].t-start_t)/(edat.nframes-1);
2471 analyse_ener(opt2bSet("-corr",NFILE,fnm),opt2fn("-corr",NFILE,fnm),
2472 bFee,bSum,bFluct,opt2parg_bSet("-nmol",npargs,ppa),
2473 bVisco,opt2fn("-vis",NFILE,fnm),
2475 start_step,start_t,frame[cur].step,frame[cur].t,
2477 nset,set,bIsEner,leg,enm,Vaver,ezero,nbmin,nbmax,
2479 calc_fluctuation_props(stdout,bDriftCorr,dt,nset,set,nmol,leg,&edat,
2482 if (opt2bSet("-f2",NFILE,fnm)) {
2483 fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
2484 reftemp, nset, set, leg, &edat, time ,oenv);
2488 const char *nxy = "-nxy";
2490 do_view(oenv,opt2fn("-o",NFILE,fnm),nxy);
2491 do_view(oenv,opt2fn_null("-ravg",NFILE,fnm),nxy);
2492 do_view(oenv,opt2fn_null("-ora",NFILE,fnm),nxy);
2493 do_view(oenv,opt2fn_null("-ort",NFILE,fnm),nxy);
2494 do_view(oenv,opt2fn_null("-oda",NFILE,fnm),nxy);
2495 do_view(oenv,opt2fn_null("-odr",NFILE,fnm),nxy);
2496 do_view(oenv,opt2fn_null("-odt",NFILE,fnm),nxy);
2497 do_view(oenv,opt2fn_null("-oten",NFILE,fnm),nxy);
2498 do_view(oenv,opt2fn_null("-odh",NFILE,fnm),nxy);