2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012,2013, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
47 #include "gmx_fatal.h"
61 #include "mtop_util.h"
65 static real minthird=-1.0/3.0,minsixth=-1.0/6.0;
83 gmx_large_int_t nsteps;
84 gmx_large_int_t npoints;
92 static double mypow(double x,double y)
100 static int *select_it(int nre,char *nm[],int *nset)
105 gmx_bool bVerbose = TRUE;
107 if ((getenv("VERBOSE")) != NULL)
110 fprintf(stderr,"Select the terms you want from the following list\n");
111 fprintf(stderr,"End your selection with 0\n");
114 for(k=0; (k<nre); ) {
115 for(j=0; (j<4) && (k<nre); j++,k++)
116 fprintf(stderr," %3d=%14s",k+1,nm[k]);
117 fprintf(stderr,"\n");
123 if(1 != scanf("%d",&n))
125 gmx_fatal(FARGS,"Error reading user input");
127 if ((n>0) && (n<=nre))
132 for(i=(*nset)=0; (i<nre); i++)
141 static void chomp(char *buf)
143 int len = strlen(buf);
145 while ((len > 0) && (buf[len-1] == '\n')) {
151 static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
154 int n,k,kk,j,i,nmatch,nind,nss;
156 gmx_bool bEOF,bVerbose = TRUE,bLong=FALSE;
157 char *ptr,buf[STRLEN];
158 const char *fm4="%3d %-14s";
159 const char *fm2="%3d %-34s";
162 if ((getenv("VERBOSE")) != NULL)
165 fprintf(stderr,"\n");
166 fprintf(stderr,"Select the terms you want from the following list by\n");
167 fprintf(stderr,"selecting either (part of) the name or the number or a combination.\n");
168 fprintf(stderr,"End your selection with an empty line or a zero.\n");
169 fprintf(stderr,"-------------------------------------------------------------------\n");
173 for(k=0; k<nre; k++) {
174 newnm[k] = strdup(nm[k].name);
175 /* Insert dashes in all the names */
176 while ((ptr = strchr(newnm[k],' ')) != NULL) {
182 fprintf(stderr,"\n");
185 for(kk=k; kk<k+4; kk++) {
186 if (kk < nre && strlen(nm[kk].name) > 14) {
194 fprintf(stderr,fm4,k+1,newnm[k]);
200 fprintf(stderr,fm2,k+1,newnm[k]);
209 fprintf(stderr,"\n\n");
215 while (!bEOF && (fgets2(buf,STRLEN-1,stdin))) {
216 /* Remove newlines */
222 /* Empty line means end of input */
223 bEOF = (strlen(buf) == 0);
228 /* First try to read an integer */
229 nss = sscanf(ptr,"%d",&nind);
231 /* Zero means end of input */
234 } else if ((1<=nind) && (nind<=nre)) {
237 fprintf(stderr,"number %d is out of range\n",nind);
241 /* Now try to read a string */
244 for(nind=0; nind<nre; nind++) {
245 if (gmx_strcasecmp(newnm[nind],ptr) == 0) {
253 for(nind=0; nind<nre; nind++) {
254 if (gmx_strncasecmp(newnm[nind],ptr,i) == 0) {
260 fprintf(stderr,"String '%s' does not match anything\n",ptr);
265 /* Look for the first space, and remove spaces from there */
266 if ((ptr = strchr(ptr,' ')) != NULL) {
269 } while (!bEOF && (ptr && (strlen(ptr) > 0)));
274 for(i=(*nset)=0; (i<nre); i++)
281 gmx_fatal(FARGS,"No energy terms selected");
283 for(i=0; (i<nre); i++)
290 static void get_dhdl_parms(const char *topnm, t_inputrec *ir)
297 /* all we need is the ir to be able to write the label */
298 read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,&mtop);
301 static void get_orires_parms(const char *topnm,
302 int *nor,int *nex,int **label,real **obs)
313 read_tpx(topnm,&ir,box,&natoms,NULL,NULL,NULL,&mtop);
314 top = gmx_mtop_generate_local_top(&mtop,&ir);
316 ip = top->idef.iparams;
317 iatom = top->idef.il[F_ORIRES].iatoms;
319 /* Count how many distance restraint there are... */
320 nb = top->idef.il[F_ORIRES].nr;
322 gmx_fatal(FARGS,"No orientation restraints in topology!\n");
328 for(i=0; i<nb; i+=3) {
329 (*label)[i/3] = ip[iatom[i]].orires.label;
330 (*obs)[i/3] = ip[iatom[i]].orires.obs;
331 if (ip[iatom[i]].orires.ex >= *nex)
332 *nex = ip[iatom[i]].orires.ex+1;
334 fprintf(stderr,"Found %d orientation restraints with %d experiments",
338 static int get_bounds(const char *topnm,
339 real **bounds,int **index,int **dr_pair,int *npairs,
340 gmx_mtop_t *mtop,gmx_localtop_t **ltop,t_inputrec *ir)
343 t_functype *functype;
345 int natoms,i,j,k,type,ftype,natom;
353 read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,mtop);
355 top = gmx_mtop_generate_local_top(mtop,ir);
358 functype = top->idef.functype;
359 ip = top->idef.iparams;
361 /* Count how many distance restraint there are... */
362 nb=top->idef.il[F_DISRES].nr;
364 gmx_fatal(FARGS,"No distance restraints in topology!\n");
366 /* Allocate memory */
371 /* Fill the bound array */
373 for(i=0; (i<top->idef.ntypes); i++) {
375 if (ftype == F_DISRES) {
377 label1 = ip[i].disres.label;
378 b[nb] = ip[i].disres.up1;
385 /* Fill the index array */
387 disres = &(top->idef.il[F_DISRES]);
388 iatom = disres->iatoms;
389 for(i=j=k=0; (i<disres->nr); ) {
391 ftype = top->idef.functype[type];
392 natom = interaction_function[ftype].nratoms+1;
393 if (label1 != top->idef.iparams[type].disres.label) {
395 label1 = top->idef.iparams[type].disres.label;
404 gmx_incons("get_bounds for distance restraints");
412 static void calc_violations(real rt[],real rav3[],int nb,int index[],
413 real bounds[],real *viol,double *st,double *sa)
415 const real sixth=1.0/6.0;
417 double rsum,rav,sumaver,sumt;
421 for(i=0; (i<nb); i++) {
424 for(j=index[i]; (j<index[i+1]); j++) {
426 viol[j] += mypow(rt[j],-3.0);
428 rsum += mypow(rt[j],-6);
430 rsum = max(0.0,mypow(rsum,-sixth)-bounds[i]);
431 rav = max(0.0,mypow(rav, -sixth)-bounds[i]);
440 static void analyse_disre(const char *voutfn, int nframes,
441 real violaver[], real bounds[], int index[],
442 int pair[], int nbounds,
443 const output_env_t oenv)
446 double sum,sumt,sumaver;
449 /* Subtract bounds from distances, to calculate violations */
450 calc_violations(violaver,violaver,
451 nbounds,pair,bounds,NULL,&sumt,&sumaver);
454 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
456 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",
459 vout=xvgropen(voutfn,"r\\S-3\\N average violations","DR Index","nm",
463 for(i=0; (i<nbounds); i++) {
464 /* Do ensemble averaging */
466 for(j=pair[i]; (j<pair[i+1]); j++)
467 sumaver += sqr(violaver[j]/nframes);
468 sumaver = max(0.0,mypow(sumaver,minsixth)-bounds[i]);
471 sum = max(sum,sumaver);
472 fprintf(vout,"%10d %10.5e\n",index[i],sumaver);
475 for(j=0; (j<dr.ndr); j++)
476 fprintf(vout,"%10d %10.5e\n",j,mypow(violaver[j]/nframes,minthird));
480 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
482 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",sum);
484 do_view(oenv,voutfn,"-graphtype bar");
487 static void einstein_visco(const char *fn,const char *fni,int nsets,
488 int nframes,real **sum,
489 real V,real T,int nsteps,double time[],
490 const output_env_t oenv)
493 double av[4],avold[4];
500 dt = (time[1]-time[0]);
503 for(i=0; i<=nsets; i++)
505 fp0=xvgropen(fni,"Shear viscosity integral",
506 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N ps)",oenv);
507 fp1=xvgropen(fn,"Shear viscosity using Einstein relation",
508 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N)",oenv);
509 for(i=1; i<nf4; i++) {
510 fac = dt*nframes/nsteps;
511 for(m=0; m<=nsets; m++)
513 for(j=0; j<nframes-i; j++) {
514 for(m=0; m<nsets; m++) {
515 di = sqr(fac*(sum[m][j+i]-sum[m][j]));
518 av[nsets] += di/nsets;
521 /* Convert to SI for the viscosity */
522 fac = (V*NANO*NANO*NANO*PICO*1e10)/(2*BOLTZMANN*T)/(nframes-i);
523 fprintf(fp0,"%10g",time[i]-time[0]);
524 for(m=0; (m<=nsets); m++) {
526 fprintf(fp0," %10g",av[m]);
529 fprintf(fp1,"%10g",0.5*(time[i]+time[i-1])-time[0]);
530 for(m=0; (m<=nsets); m++) {
531 fprintf(fp1," %10g",(av[m]-avold[m])/dt);
551 gmx_large_int_t nst_min;
554 static void clear_ee_sum(ee_sum_t *ees)
562 static void add_ee_sum(ee_sum_t *ees,double sum,int np)
568 static void add_ee_av(ee_sum_t *ees)
572 av = ees->sum/ees->np;
579 static double calc_ee2(int nb,ee_sum_t *ees)
581 return (ees->sav2/nb - dsqr(ees->sav/nb))/(nb - 1);
584 static void set_ee_av(ener_ee_t *eee)
588 char buf[STEPSTRSIZE];
589 fprintf(debug,"Storing average for err.est.: %s steps\n",
590 gmx_step_str(eee->nst,buf));
592 add_ee_av(&eee->sum);
594 if (eee->b == 1 || eee->nst < eee->nst_min)
596 eee->nst_min = eee->nst;
601 static void calc_averages(int nset,enerdata_t *edat,int nbmin,int nbmax)
604 double sum,sum2,sump,see2;
605 gmx_large_int_t steps,np,p,bound_nb;
609 double x,sx,sy,sxx,sxy;
612 /* Check if we have exact statistics over all points */
613 for(i=0; i<nset; i++)
616 ed->bExactStat = FALSE;
617 if (edat->npoints > 0)
619 /* All energy file sum entries 0 signals no exact sums.
620 * But if all energy values are 0, we still have exact sums.
623 for(f=0; f<edat->nframes && !ed->bExactStat; f++)
625 if (ed->ener[i] != 0)
629 ed->bExactStat = (ed->es[f].sum != 0);
633 ed->bExactStat = TRUE;
639 for(i=0; i<nset; i++)
650 for(nb=nbmin; nb<=nbmax; nb++)
653 clear_ee_sum(&eee[nb].sum);
657 for(f=0; f<edat->nframes; f++)
663 /* Add the sum and the sum of variances to the totals. */
669 sum2 += dsqr(sum/np - (sum + es->sum)/(np + p))
675 /* Add a single value to the sum and sum of squares. */
681 /* sum has to be increased after sum2 */
685 /* For the linear regression use variance 1/p.
686 * Note that sump is the sum, not the average, so we don't need p*.
688 x = edat->step[f] - 0.5*(edat->steps[f] - 1);
694 for(nb=nbmin; nb<=nbmax; nb++)
696 /* Check if the current end step is closer to the desired
697 * block boundary than the next end step.
699 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
700 if (eee[nb].nst > 0 &&
701 bound_nb - edat->step[f-1]*nb < edat->step[f]*nb - bound_nb)
711 eee[nb].nst += edat->step[f] - edat->step[f-1];
715 add_ee_sum(&eee[nb].sum,es->sum,edat->points[f]);
719 add_ee_sum(&eee[nb].sum,edat->s[i].ener[f],1);
721 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
722 if (edat->step[f]*nb >= bound_nb)
729 edat->s[i].av = sum/np;
732 edat->s[i].rmsd = sqrt(sum2/np);
736 edat->s[i].rmsd = sqrt(sum2/np - dsqr(edat->s[i].av));
739 if (edat->nframes > 1)
741 edat->s[i].slope = (np*sxy - sx*sy)/(np*sxx - sx*sx);
745 edat->s[i].slope = 0;
750 for(nb=nbmin; nb<=nbmax; nb++)
752 /* Check if we actually got nb blocks and if the smallest
753 * block is not shorter than 80% of the average.
757 char buf1[STEPSTRSIZE],buf2[STEPSTRSIZE];
758 fprintf(debug,"Requested %d blocks, we have %d blocks, min %s nsteps %s\n",
760 gmx_step_str(eee[nb].nst_min,buf1),
761 gmx_step_str(edat->nsteps,buf2));
763 if (eee[nb].b == nb && 5*nb*eee[nb].nst_min >= 4*edat->nsteps)
765 see2 += calc_ee2(nb,&eee[nb].sum);
771 edat->s[i].ee = sqrt(see2/nee);
781 static enerdata_t *calc_sum(int nset,enerdata_t *edat,int nbmin,int nbmax)
792 snew(s->ener,esum->nframes);
793 snew(s->es ,esum->nframes);
795 s->bExactStat = TRUE;
797 for(i=0; i<nset; i++)
799 if (!edat->s[i].bExactStat)
801 s->bExactStat = FALSE;
803 s->slope += edat->s[i].slope;
806 for(f=0; f<edat->nframes; f++)
809 for(i=0; i<nset; i++)
811 sum += edat->s[i].ener[f];
815 for(i=0; i<nset; i++)
817 sum += edat->s[i].es[f].sum;
823 calc_averages(1,esum,nbmin,nbmax);
828 static char *ee_pr(double ee,char *buf)
835 sprintf(buf,"%s","--");
839 /* Round to two decimals by printing. */
840 sprintf(tmp,"%.1e",ee);
841 sscanf(tmp,"%lf",&rnd);
842 sprintf(buf,"%g",rnd);
848 static void remove_drift(int nset,int nbmin,int nbmax,real dt,enerdata_t *edat)
850 /* Remove the drift by performing a fit to y = ax+b.
851 Uses 5 iterations. */
853 double delta,d,sd,sd2;
855 edat->npoints = edat->nframes;
856 edat->nsteps = edat->nframes;
860 for(i=0; (i<nset); i++)
862 delta = edat->s[i].slope*dt;
865 fprintf(debug,"slope for set %d is %g\n",i,edat->s[i].slope);
867 for(j=0; (j<edat->nframes); j++)
869 edat->s[i].ener[j] -= j*delta;
870 edat->s[i].es[j].sum = 0;
871 edat->s[i].es[j].sum2 = 0;
874 calc_averages(nset,edat,nbmin,nbmax);
878 static void calc_fluctuation_props(FILE *fp,
879 gmx_bool bDriftCorr,real dt,
880 int nset,int set[],int nmol,
881 char **leg,enerdata_t *edat,
885 double vvhh,vv,v,h,hh2,vv2,varv,hh,varh,tt,cv,cp,alpha,kappa,dcp,et,varet;
887 enum { eVol, eEnth, eTemp, eEtot, eNR };
888 const char *my_ener[] = { "Volume", "Enthalpy", "Temperature", "Total Energy" };
891 NANO3 = NANO*NANO*NANO;
894 fprintf(fp,"\nYou may want to use the -driftcorr flag in order to correct\n"
895 "for spurious drift in the graphs. Note that this is not\n"
896 "a substitute for proper equilibration and sampling!\n");
900 remove_drift(nset,nbmin,nbmax,dt,edat);
902 for(i=0; (i<eNR); i++)
904 for(ii[i]=0; (ii[i]<nset &&
905 (gmx_strcasecmp(leg[ii[i]],my_ener[i]) != 0)); ii[i]++)
908 fprintf(fp,"Found %s data.\n",my_ener[i]);
910 /* Compute it all! */
911 vvhh = alpha = kappa = cp = dcp = cv = NOTSET;
915 if (ii[eTemp] < nset)
917 tt = edat->s[ii[eTemp]].av;
921 if ((ii[eVol] < nset) && (ii[eTemp] < nset))
923 vv = edat->s[ii[eVol]].av*NANO3;
924 varv = dsqr(edat->s[ii[eVol]].rmsd*NANO3);
925 kappa = (varv/vv)/(BOLTZMANN*tt);
929 if ((ii[eEnth] < nset) && (ii[eTemp] < nset))
931 hh = KILO*edat->s[ii[eEnth]].av/AVOGADRO;
932 varh = dsqr(KILO*edat->s[ii[eEnth]].rmsd/AVOGADRO);
933 cp = AVOGADRO*((varh/nmol)/(BOLTZMANN*tt*tt));
937 if ((ii[eEtot] < nset) && (hh == NOTSET) && (tt != NOTSET))
939 /* Only compute cv in constant volume runs, which we can test
940 by checking whether the enthalpy was computed.
942 et = edat->s[ii[eEtot]].av;
943 varet = sqr(edat->s[ii[eEtot]].rmsd);
944 cv = KILO*((varet/nmol)/(BOLTZ*tt*tt));
947 if ((ii[eVol] < nset) && (ii[eEnth] < nset) && (ii[eTemp] < nset))
950 for(j=0; (j<edat->nframes); j++)
952 v = edat->s[ii[eVol]].ener[j]*NANO3;
953 h = KILO*edat->s[ii[eEnth]].ener[j]/AVOGADRO;
956 vvhh /= edat->nframes;
957 alpha = (vvhh-vv*hh)/(vv*BOLTZMANN*tt*tt);
958 dcp = (vv*AVOGADRO/nmol)*tt*sqr(alpha)/(kappa);
964 fprintf(fp,"\nWARNING: nmol = %d, this may not be what you want.\n",
966 fprintf(fp,"\nTemperature dependent fluctuation properties at T = %g.\n",tt);
967 fprintf(fp,"\nHeat capacities obtained from fluctuations do *not* include\n");
968 fprintf(fp,"quantum corrections. If you want to get a more accurate estimate\n");
969 fprintf(fp,"please use the g_dos program.\n\n");
970 fprintf(fp,"WARNING: Please verify that your simulations are converged and perform\n"
971 "a block-averaging error analysis (not implemented in g_energy yet)\n");
976 fprintf(fp,"varv = %10g (m^6)\n",varv*AVOGADRO/nmol);
978 fprintf(fp,"vvhh = %10g (m^3 J)\n",vvhh);
981 fprintf(fp,"Volume = %10g m^3/mol\n",
984 fprintf(fp,"Enthalpy = %10g kJ/mol\n",
985 hh*AVOGADRO/(KILO*nmol));
987 fprintf(fp,"Coefficient of Thermal Expansion Alpha_P = %10g (1/K)\n",
991 fprintf(fp,"Isothermal Compressibility Kappa = %10g (J/m^3)\n",
993 fprintf(fp,"Adiabatic bulk modulus = %10g (m^3/J)\n",
997 fprintf(fp,"Heat capacity at constant pressure Cp = %10g J/mol K\n",
1000 fprintf(fp,"Heat capacity at constant volume Cv = %10g J/mol K\n",
1003 fprintf(fp,"Cp-Cv = %10g J/mol K\n",
1005 please_cite(fp,"Allen1987a");
1009 fprintf(fp,"You should select the temperature in order to obtain fluctuation properties.\n");
1013 static void analyse_ener(gmx_bool bCorr,const char *corrfn,
1014 gmx_bool bFee,gmx_bool bSum,gmx_bool bFluct,gmx_bool bTempFluct,
1015 gmx_bool bVisco,const char *visfn,int nmol,
1016 gmx_large_int_t start_step,double start_t,
1017 gmx_large_int_t step,double t,
1018 double time[], real reftemp,
1020 int nset,int set[],gmx_bool *bIsEner,
1021 char **leg,gmx_enxnm_t *enm,
1022 real Vaver,real ezero,
1023 int nbmin,int nbmax,
1024 const output_env_t oenv)
1027 /* Check out the printed manual for equations! */
1028 double Dt,aver,stddev,errest,delta_t,totaldrift;
1029 enerdata_t *esum=NULL;
1030 real xxx,integral,intBulk,Temp=0,Pres=0;
1031 real sfrac,oldfrac,diffsum,diffav,fstep,pr_aver,pr_stddev,pr_errest;
1032 double beta=0,expE,expEtot,*fee=NULL;
1033 gmx_large_int_t nsteps;
1034 int nexact,nnotexact;
1038 char buf[256],eebuf[100];
1040 nsteps = step - start_step + 1;
1042 fprintf(stdout,"Not enough steps (%s) for statistics\n",
1043 gmx_step_str(nsteps,buf));
1046 /* Calculate the time difference */
1047 delta_t = t - start_t;
1049 fprintf(stdout,"\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
1050 gmx_step_str(nsteps,buf),start_t,t,nset);
1052 calc_averages(nset,edat,nbmin,nbmax);
1055 esum = calc_sum(nset,edat,nbmin,nbmax);
1058 if (edat->npoints == 0) {
1064 for(i=0; (i<nset); i++) {
1065 if (edat->s[i].bExactStat) {
1073 if (nnotexact == 0) {
1074 fprintf(stdout,"All statistics are over %s points\n",
1075 gmx_step_str(edat->npoints,buf));
1076 } else if (nexact == 0 || edat->npoints == edat->nframes) {
1077 fprintf(stdout,"All statistics are over %d points (frames)\n",
1080 fprintf(stdout,"The term%s",nnotexact==1 ? "" : "s");
1081 for(i=0; (i<nset); i++) {
1082 if (!edat->s[i].bExactStat) {
1083 fprintf(stdout," '%s'",leg[i]);
1086 fprintf(stdout," %s has statistics over %d points (frames)\n",
1087 nnotexact==1 ? "is" : "are",edat->nframes);
1088 fprintf(stdout,"All other statistics are over %s points\n",
1089 gmx_step_str(edat->npoints,buf));
1091 fprintf(stdout,"\n");
1093 fprintf(stdout,"%-24s %10s %10s %10s %10s",
1094 "Energy","Average","Err.Est.","RMSD","Tot-Drift");
1096 fprintf(stdout," %10s\n","-kT ln<e^(E/kT)>");
1098 fprintf(stdout,"\n");
1099 fprintf(stdout,"-------------------------------------------------------------------------------\n");
1101 /* Initiate locals, only used with -sum */
1104 beta = 1.0/(BOLTZ*reftemp);
1107 for(i=0; (i<nset); i++) {
1108 aver = edat->s[i].av;
1109 stddev = edat->s[i].rmsd;
1110 errest = edat->s[i].ee;
1114 for(j=0; (j<edat->nframes); j++) {
1115 expE += exp(beta*(edat->s[i].ener[j] - aver)/nmol);
1118 expEtot+=expE/edat->nframes;
1120 fee[i] = log(expE/edat->nframes)/beta + aver/nmol;
1122 if (strstr(leg[i],"empera") != NULL) {
1124 } else if (strstr(leg[i],"olum") != NULL) {
1126 } else if (strstr(leg[i],"essure") != NULL) {
1130 pr_aver = aver/nmol-ezero;
1131 pr_stddev = stddev/nmol;
1132 pr_errest = errest/nmol;
1140 /* Multiply the slope in steps with the number of steps taken */
1141 totaldrift = (edat->nsteps - 1)*edat->s[i].slope;
1147 fprintf(stdout,"%-24s %10g %10s %10g %10g",
1148 leg[i],pr_aver,ee_pr(pr_errest,eebuf),pr_stddev,totaldrift);
1150 fprintf(stdout," %10g",fee[i]);
1152 fprintf(stdout," (%s)\n",enm[set[i]].unit);
1155 for(j=0; (j<edat->nframes); j++)
1156 edat->s[i].ener[j] -= aver;
1160 totaldrift = (edat->nsteps - 1)*esum->s[0].slope;
1161 fprintf(stdout,"%-24s %10g %10s %10s %10g (%s)",
1162 "Total",esum->s[0].av/nmol,ee_pr(esum->s[0].ee/nmol,eebuf),
1163 "--",totaldrift/nmol,enm[set[0]].unit);
1164 /* pr_aver,pr_stddev,a,totaldrift */
1166 fprintf(stdout," %10g %10g\n",
1167 log(expEtot)/beta + esum->s[0].av/nmol,log(expEtot)/beta);
1169 fprintf(stdout,"\n");
1172 /* Do correlation function */
1173 if (edat->nframes > 1)
1175 Dt = delta_t/(edat->nframes - 1);
1182 const char* leg[] = { "Shear", "Bulk" };
1187 /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
1189 /* Symmetrise tensor! (and store in first three elements)
1190 * And subtract average pressure!
1193 for(i=0; i<12; i++) {
1194 snew(eneset[i],edat->nframes);
1197 for(i=0; i<3; i++) {
1198 snew(enesum[i],edat->nframes);
1200 for(i=0; (i<edat->nframes); i++) {
1201 eneset[0][i] = 0.5*(edat->s[1].ener[i]+edat->s[3].ener[i]);
1202 eneset[1][i] = 0.5*(edat->s[2].ener[i]+edat->s[6].ener[i]);
1203 eneset[2][i] = 0.5*(edat->s[5].ener[i]+edat->s[7].ener[i]);
1204 for(j=3; j<=11; j++) {
1205 eneset[j][i] = edat->s[j].ener[i];
1207 eneset[11][i] -= Pres;
1208 enesum[0][i] = 0.5*(edat->s[1].es[i].sum+edat->s[3].es[i].sum);
1209 enesum[1][i] = 0.5*(edat->s[2].es[i].sum+edat->s[6].es[i].sum);
1210 enesum[2][i] = 0.5*(edat->s[5].es[i].sum+edat->s[7].es[i].sum);
1213 einstein_visco("evisco.xvg","eviscoi.xvg",
1214 3,edat->nframes,enesum,Vaver,Temp,nsteps,time,oenv);
1216 /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
1217 /* Do it for shear viscosity */
1218 strcpy(buf,"Shear Viscosity");
1219 low_do_autocorr(corrfn,oenv,buf,edat->nframes,3,
1220 (edat->nframes+1)/2,eneset,Dt,
1221 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1223 /* Now for bulk viscosity */
1224 strcpy(buf,"Bulk Viscosity");
1225 low_do_autocorr(corrfn,oenv,buf,edat->nframes,1,
1226 (edat->nframes+1)/2,&(eneset[11]),Dt,
1227 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1229 factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
1230 fp=xvgropen(visfn,buf,"Time (ps)","\\8h\\4 (cp)",oenv);
1231 xvgr_legend(fp,asize(leg),leg,oenv);
1233 /* Use trapezium rule for integration */
1236 nout = get_acfnout();
1237 if ((nout < 2) || (nout >= edat->nframes/2))
1238 nout = edat->nframes/2;
1239 for(i=1; (i<nout); i++)
1241 integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
1242 intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
1243 fprintf(fp,"%10g %10g %10g\n",(i*Dt),integral,intBulk);
1249 strcpy(buf,"Autocorrelation of Energy Fluctuations");
1251 strcpy(buf,"Energy Autocorrelation");
1253 do_autocorr(corrfn,oenv,buf,edat->nframes,
1255 bSum ? &edat->s[nset-1].ener : eneset,
1256 (delta_t/edat->nframes),eacNormal,FALSE);
1262 static void print_time(FILE *fp,double t)
1264 fprintf(fp,"%12.6f",t);
1267 static void print1(FILE *fp,gmx_bool bDp,real e)
1270 fprintf(fp," %16.12f",e);
1272 fprintf(fp," %10.6f",e);
1275 static void fec(const char *ene2fn, const char *runavgfn,
1276 real reftemp, int nset, int set[], char *leg[],
1277 enerdata_t *edat, double time[],
1278 const output_env_t oenv)
1280 const char* ravgleg[] = { "\\8D\\4E = E\\sB\\N-E\\sA\\N",
1281 "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N" };
1284 int nre,timecheck,step,nenergy,nenergy2,maxenergy;
1290 gmx_enxnm_t *enm=NULL;
1294 /* read second energy file */
1297 enx = open_enx(ene2fn,"r");
1298 do_enxnms(enx,&(fr->nre),&enm);
1300 snew(eneset2,nset+1);
1305 /* This loop searches for the first frame (when -b option is given),
1306 * or when this has been found it reads just one energy frame
1309 bCont = do_enx(enx,fr);
1312 timecheck = check_times(fr->t);
1314 } while (bCont && (timecheck < 0));
1316 /* Store energies for analysis afterwards... */
1317 if ((timecheck == 0) && bCont) {
1319 if ( nenergy2 >= maxenergy ) {
1321 for(i=0; i<=nset; i++)
1322 srenew(eneset2[i],maxenergy);
1324 if (fr->t != time[nenergy2])
1325 fprintf(stderr,"\nWARNING time mismatch %g!=%g at frame %s\n",
1326 fr->t, time[nenergy2], gmx_step_str(fr->step,buf));
1327 for(i=0; i<nset; i++)
1328 eneset2[i][nenergy2] = fr->ener[set[i]].e;
1332 } while (bCont && (timecheck == 0));
1335 if (edat->nframes != nenergy2) {
1336 fprintf(stderr,"\nWARNING file length mismatch %d!=%d\n",
1337 edat->nframes,nenergy2);
1339 nenergy = min(edat->nframes,nenergy2);
1341 /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
1344 fp=xvgropen(runavgfn,"Running average free energy difference",
1345 "Time (" unit_time ")","\\8D\\4E (" unit_energy ")",oenv);
1346 xvgr_legend(fp,asize(ravgleg),ravgleg,oenv);
1348 fprintf(stdout,"\n%-24s %10s\n",
1349 "Energy","dF = -kT ln < exp(-(EB-EA)/kT) >A");
1351 beta = 1.0/(BOLTZ*reftemp);
1352 for(i=0; i<nset; i++) {
1353 if (gmx_strcasecmp(leg[i],enm[set[i]].name)!=0)
1354 fprintf(stderr,"\nWARNING energy set name mismatch %s!=%s\n",
1355 leg[i],enm[set[i]].name);
1356 for(j=0; j<nenergy; j++) {
1357 dE = eneset2[i][j] - edat->s[i].ener[j];
1358 sum += exp(-dE*beta);
1360 fprintf(fp,"%10g %10g %10g\n",
1361 time[j], dE, -BOLTZ*reftemp*log(sum/(j+1)) );
1363 aver = -BOLTZ*reftemp*log(sum/nenergy);
1364 fprintf(stdout,"%-24s %10g\n",leg[i],aver);
1371 static void do_dhdl(t_enxframe *fr, t_inputrec *ir, FILE **fp_dhdl,
1372 const char *filename, gmx_bool bDp,
1373 int *blocks, int *hists, int *samples, int *nlambdas,
1374 const output_env_t oenv)
1376 const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
1377 char title[STRLEN],label_x[STRLEN],label_y[STRLEN], legend[STRLEN];
1379 gmx_bool first=FALSE;
1380 int nblock_hist=0, nblock_dh=0, nblock_dhcoll=0;
1383 double temp=0, start_time=0, delta_time=0, start_lambda=0, delta_lambda=0;
1385 double *native_lambda_vec=NULL;
1386 const char **lambda_components=NULL;
1388 gmx_bool changing_lambda=FALSE;
1389 int lambda_fep_state;
1391 /* now count the blocks & handle the global dh data */
1392 for(i=0;i<fr->nblock;i++)
1394 if (fr->block[i].id == enxDHHIST)
1398 else if (fr->block[i].id == enxDH)
1402 else if (fr->block[i].id == enxDHCOLL)
1405 if ( (fr->block[i].nsub < 1) ||
1406 (fr->block[i].sub[0].type != xdr_datatype_double) ||
1407 (fr->block[i].sub[0].nr < 5))
1409 gmx_fatal(FARGS, "Unexpected block data");
1412 /* read the data from the DHCOLL block */
1413 temp = fr->block[i].sub[0].dval[0];
1414 start_time = fr->block[i].sub[0].dval[1];
1415 delta_time = fr->block[i].sub[0].dval[2];
1416 start_lambda = fr->block[i].sub[0].dval[3];
1417 delta_lambda = fr->block[i].sub[0].dval[4];
1418 changing_lambda = (delta_lambda != 0);
1419 if (fr->block[i].nsub > 1)
1421 lambda_fep_state=fr->block[i].sub[1].ival[0];
1422 if (n_lambda_vec==0)
1424 n_lambda_vec=fr->block[i].sub[1].ival[1];
1428 if (n_lambda_vec!=fr->block[i].sub[1].ival[1])
1431 "Unexpected change of basis set in lambda");
1434 if (lambda_components == NULL)
1435 snew(lambda_components, n_lambda_vec);
1436 if (native_lambda_vec == NULL)
1437 snew(native_lambda_vec, n_lambda_vec);
1438 for(j=0;j<n_lambda_vec;j++)
1440 native_lambda_vec[j] = fr->block[i].sub[0].dval[5+j];
1441 lambda_components[j] =
1442 efpt_singular_names[fr->block[i].sub[1].ival[2+j]];
1448 if (nblock_hist == 0 && nblock_dh == 0)
1450 /* don't do anything */
1453 if (nblock_hist>0 && nblock_dh>0)
1455 gmx_fatal(FARGS, "This energy file contains both histogram dhdl data and non-histogram dhdl data. Don't know what to do.");
1461 /* we have standard, non-histogram data --
1462 call open_dhdl to open the file */
1463 /* TODO this is an ugly hack that needs to be fixed: this will only
1464 work if the order of data is always the same and if we're
1465 only using the g_energy compiled with the mdrun that produced
1467 *fp_dhdl=open_dhdl(filename,ir,oenv);
1471 sprintf(title,"N(%s)",deltag);
1472 sprintf(label_x,"%s (%s)",deltag,unit_energy);
1473 sprintf(label_y,"Samples");
1474 *fp_dhdl=xvgropen_type(filename, title, label_x, label_y, exvggtXNY,oenv);
1475 sprintf(buf,"T = %g (K), %s = %g", temp, lambda, start_lambda);
1476 xvgr_subtitle(*fp_dhdl,buf,oenv);
1480 (*hists)+=nblock_hist;
1481 (*blocks)+=nblock_dh;
1482 (*nlambdas) = nblock_hist+nblock_dh;
1484 /* write the data */
1485 if (nblock_hist > 0)
1487 gmx_large_int_t sum=0;
1489 for(i=0;i<fr->nblock;i++)
1491 t_enxblock *blk=&(fr->block[i]);
1492 if (blk->id==enxDHHIST)
1494 double foreign_lambda, dx;
1496 int nhist, derivative;
1498 /* check the block types etc. */
1499 if ( (blk->nsub < 2) ||
1500 (blk->sub[0].type != xdr_datatype_double) ||
1501 (blk->sub[1].type != xdr_datatype_large_int) ||
1502 (blk->sub[0].nr < 2) ||
1503 (blk->sub[1].nr < 2) )
1505 gmx_fatal(FARGS, "Unexpected block data in file");
1507 foreign_lambda=blk->sub[0].dval[0];
1508 dx=blk->sub[0].dval[1];
1509 nhist=blk->sub[1].lval[0];
1510 derivative=blk->sub[1].lval[1];
1511 for(j=0;j<nhist;j++)
1514 x0=blk->sub[1].lval[2+j];
1518 sprintf(legend, "N(%s(%s=%g) | %s=%g)",
1519 deltag, lambda, foreign_lambda,
1520 lambda, start_lambda);
1524 sprintf(legend, "N(%s | %s=%g)",
1525 dhdl, lambda, start_lambda);
1529 xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv);
1531 for(k=0;k<blk->sub[j+2].nr;k++)
1536 hist=blk->sub[j+2].ival[k];
1539 fprintf(*fp_dhdl,"%g %d\n%g %d\n", xmin, hist,
1543 /* multiple histogram data blocks in one histogram
1544 mean that the second one is the reverse of the first one:
1545 for dhdl derivatives, it's important to know both the
1546 maximum and minimum values */
1551 (*samples) += (int)(sum/nblock_hist);
1557 char **setnames=NULL;
1558 int nnames=nblock_dh;
1560 for(i=0;i<fr->nblock;i++)
1562 t_enxblock *blk=&(fr->block[i]);
1563 if (blk->id == enxDH)
1571 if (len!=blk->sub[2].nr)
1573 gmx_fatal(FARGS, "Length inconsistency in dhdl data");
1582 double time=start_time + delta_time*i;
1584 fprintf(*fp_dhdl,"%.4f ", time);
1586 for(j=0;j<fr->nblock;j++)
1588 t_enxblock *blk=&(fr->block[j]);
1589 if (blk->id == enxDH)
1592 if (blk->sub[2].type == xdr_datatype_float)
1594 value=blk->sub[2].fval[i];
1598 value=blk->sub[2].dval[i];
1600 /* we need to decide which data type it is based on the count*/
1602 if (j==1 && ir->bExpanded)
1604 fprintf(*fp_dhdl,"%4d", (int)value); /* if expanded ensembles and zero, this is a state value, it's an integer. We need a cleaner conditional than if j==1! */
1607 fprintf(*fp_dhdl," %#.12g", value); /* print normal precision */
1611 fprintf(*fp_dhdl," %#.8g", value); /* print normal precision */
1616 fprintf(*fp_dhdl, "\n");
1622 int gmx_energy(int argc,char *argv[])
1624 const char *desc[] = {
1626 "[TT]g_energy[tt] extracts energy components or distance restraint",
1627 "data from an energy file. The user is prompted to interactively",
1628 "select the desired energy terms.[PAR]",
1630 "Average, RMSD, and drift are calculated with full precision from the",
1631 "simulation (see printed manual). Drift is calculated by performing",
1632 "a least-squares fit of the data to a straight line. The reported total drift",
1633 "is the difference of the fit at the first and last point.",
1634 "An error estimate of the average is given based on a block averages",
1635 "over 5 blocks using the full-precision averages. The error estimate",
1636 "can be performed over multiple block lengths with the options",
1637 "[TT]-nbmin[tt] and [TT]-nbmax[tt].",
1638 "[BB]Note[bb] that in most cases the energy files contains averages over all",
1639 "MD steps, or over many more points than the number of frames in",
1640 "energy file. This makes the [TT]g_energy[tt] statistics output more accurate",
1641 "than the [TT].xvg[tt] output. When exact averages are not present in the energy",
1642 "file, the statistics mentioned above are simply over the single, per-frame",
1643 "energy values.[PAR]",
1645 "The term fluctuation gives the RMSD around the least-squares fit.[PAR]",
1647 "Some fluctuation-dependent properties can be calculated provided",
1648 "the correct energy terms are selected, and that the command line option",
1649 "[TT]-fluct_props[tt] is given. The following properties",
1650 "will be computed:[BR]",
1651 "Property Energy terms needed[BR]",
1652 "---------------------------------------------------[BR]",
1653 "Heat capacity C[SUB]p[sub] (NPT sims): Enthalpy, Temp [BR]",
1654 "Heat capacity C[SUB]v[sub] (NVT sims): Etot, Temp [BR]",
1655 "Thermal expansion coeff. (NPT): Enthalpy, Vol, Temp[BR]",
1656 "Isothermal compressibility: Vol, Temp [BR]",
1657 "Adiabatic bulk modulus: Vol, Temp [BR]",
1658 "---------------------------------------------------[BR]",
1659 "You always need to set the number of molecules [TT]-nmol[tt].",
1660 "The C[SUB]p[sub]/C[SUB]v[sub] computations do [BB]not[bb] include any corrections",
1661 "for quantum effects. Use the [TT]g_dos[tt] program if you need that (and you do).[PAR]"
1662 "When the [TT]-viol[tt] option is set, the time averaged",
1663 "violations are plotted and the running time-averaged and",
1664 "instantaneous sum of violations are recalculated. Additionally",
1665 "running time-averaged and instantaneous distances between",
1666 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
1668 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
1669 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
1670 "The first two options plot the orientation, the last three the",
1671 "deviations of the orientations from the experimental values.",
1672 "The options that end on an 'a' plot the average over time",
1673 "as a function of restraint. The options that end on a 't'",
1674 "prompt the user for restraint label numbers and plot the data",
1675 "as a function of time. Option [TT]-odr[tt] plots the RMS",
1676 "deviation as a function of restraint.",
1677 "When the run used time or ensemble averaged orientation restraints,",
1678 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
1679 "not ensemble-averaged orientations and deviations instead of",
1680 "the time and ensemble averages.[PAR]",
1682 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
1683 "tensor for each orientation restraint experiment. With option",
1684 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
1686 "Option [TT]-odh[tt] extracts and plots the free energy data",
1687 "(Hamiltoian differences and/or the Hamiltonian derivative dhdl)",
1688 "from the [TT]ener.edr[tt] file.[PAR]",
1690 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
1691 "difference with an ideal gas state: [BR]",
1692 " [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]",
1693 " [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]",
1694 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
1695 "the average is over the ensemble (or time in a trajectory).",
1696 "Note that this is in principle",
1697 "only correct when averaging over the whole (Boltzmann) ensemble",
1698 "and using the potential energy. This also allows for an entropy",
1699 "estimate using:[BR]",
1700 " [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]",
1701 " [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",
1704 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
1705 "difference is calculated [BR] dF = -kT [LN][CHEVRON][EXP]-(E[SUB]B[sub]-E[SUB]A[sub])/kT[exp][chevron][SUB]A[sub][ln] ,",
1706 "where E[SUB]A[sub] and E[SUB]B[sub] are the energies from the first and second energy",
1707 "files, and the average is over the ensemble A. The running average",
1708 "of the free energy difference is printed to a file specified by [TT]-ravg[tt].",
1709 "[BB]Note[bb] that the energies must both be calculated from the same trajectory."
1712 static gmx_bool bSum=FALSE,bFee=FALSE,bPrAll=FALSE,bFluct=FALSE,bDriftCorr=FALSE;
1713 static gmx_bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE,bFluctProps=FALSE;
1714 static int skip=0,nmol=1,nbmin=5,nbmax=5;
1715 static real reftemp=300.0,ezero=0;
1717 { "-fee", FALSE, etBOOL, {&bFee},
1718 "Do a free energy estimate" },
1719 { "-fetemp", FALSE, etREAL,{&reftemp},
1720 "Reference temperature for free energy calculation" },
1721 { "-zero", FALSE, etREAL, {&ezero},
1722 "Subtract a zero-point energy" },
1723 { "-sum", FALSE, etBOOL, {&bSum},
1724 "Sum the energy terms selected rather than display them all" },
1725 { "-dp", FALSE, etBOOL, {&bDp},
1726 "Print energies in high precision" },
1727 { "-nbmin", FALSE, etINT, {&nbmin},
1728 "Minimum number of blocks for error estimate" },
1729 { "-nbmax", FALSE, etINT, {&nbmax},
1730 "Maximum number of blocks for error estimate" },
1731 { "-mutot",FALSE, etBOOL, {&bMutot},
1732 "Compute the total dipole moment from the components" },
1733 { "-skip", FALSE, etINT, {&skip},
1734 "Skip number of frames between data points" },
1735 { "-aver", FALSE, etBOOL, {&bPrAll},
1736 "Also print the exact average and rmsd stored in the energy frames (only when 1 term is requested)" },
1737 { "-nmol", FALSE, etINT, {&nmol},
1738 "Number of molecules in your sample: the energies are divided by this number" },
1739 { "-fluct_props", FALSE, etBOOL, {&bFluctProps},
1740 "Compute properties based on energy fluctuations, like heat capacity" },
1741 { "-driftcorr", FALSE, etBOOL, {&bDriftCorr},
1742 "Useful only for calculations of fluctuation properties. The drift in the observables will be subtracted before computing the fluctuation properties."},
1743 { "-fluc", FALSE, etBOOL, {&bFluct},
1744 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
1745 { "-orinst", FALSE, etBOOL, {&bOrinst},
1746 "Analyse instantaneous orientation data" },
1747 { "-ovec", FALSE, etBOOL, {&bOvec},
1748 "Also plot the eigenvectors with [TT]-oten[tt]" }
1750 const char* drleg[] = {
1754 static const char *setnm[] = {
1755 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
1756 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
1757 "Volume", "Pressure"
1760 FILE *out=NULL,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
1766 gmx_localtop_t *top=NULL;
1770 gmx_enxnm_t *enm=NULL;
1771 t_enxframe *frame,*fr=NULL;
1773 #define NEXT (1-cur)
1774 int nre,teller,teller_disre,nfr;
1775 gmx_large_int_t start_step;
1776 int nor=0,nex=0,norfr=0,enx_i=0;
1778 real *bounds=NULL,*violaver=NULL,*oobs=NULL,*orient=NULL,*odrms=NULL;
1779 int *index=NULL,*pair=NULL,norsel=0,*orsel=NULL,*or_label=NULL;
1780 int nbounds=0,npairs;
1781 gmx_bool bDisRe,bDRAll,bORA,bORT,bODA,bODR,bODT,bORIRE,bOTEN,bDHDL;
1782 gmx_bool bFoundStart,bCont,bEDR,bVisco;
1783 double sum,sumaver,sumt,ener,dbl;
1786 int *set=NULL,i,j,k,nset,sss;
1787 gmx_bool *bIsEner=NULL;
1788 char **pairleg,**odtleg,**otenleg;
1791 char *anm_j,*anm_k,*resnm_j,*resnm_k;
1792 int resnr_j,resnr_k;
1793 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
1796 t_enxblock *blk=NULL;
1797 t_enxblock *blk_disre=NULL;
1799 int dh_blocks=0, dh_hists=0, dh_samples=0, dh_lambdas=0;
1802 { efEDR, "-f", NULL, ffREAD },
1803 { efEDR, "-f2", NULL, ffOPTRD },
1804 { efTPX, "-s", NULL, ffOPTRD },
1805 { efXVG, "-o", "energy", ffWRITE },
1806 { efXVG, "-viol", "violaver",ffOPTWR },
1807 { efXVG, "-pairs","pairs", ffOPTWR },
1808 { efXVG, "-ora", "orienta", ffOPTWR },
1809 { efXVG, "-ort", "orientt", ffOPTWR },
1810 { efXVG, "-oda", "orideva", ffOPTWR },
1811 { efXVG, "-odr", "oridevr", ffOPTWR },
1812 { efXVG, "-odt", "oridevt", ffOPTWR },
1813 { efXVG, "-oten", "oriten", ffOPTWR },
1814 { efXVG, "-corr", "enecorr", ffOPTWR },
1815 { efXVG, "-vis", "visco", ffOPTWR },
1816 { efXVG, "-ravg", "runavgdf",ffOPTWR },
1817 { efXVG, "-odh", "dhdl" ,ffOPTWR }
1819 #define NFILE asize(fnm)
1823 CopyRight(stderr,argv[0]);
1825 ppa = add_acf_pargs(&npargs,pa);
1826 parse_common_args(&argc,argv,
1827 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
1828 NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
1830 bDRAll = opt2bSet("-pairs",NFILE,fnm);
1831 bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
1832 bORA = opt2bSet("-ora",NFILE,fnm);
1833 bORT = opt2bSet("-ort",NFILE,fnm);
1834 bODA = opt2bSet("-oda",NFILE,fnm);
1835 bODR = opt2bSet("-odr",NFILE,fnm);
1836 bODT = opt2bSet("-odt",NFILE,fnm);
1837 bORIRE = bORA || bORT || bODA || bODR || bODT;
1838 bOTEN = opt2bSet("-oten",NFILE,fnm);
1839 bDHDL = opt2bSet("-odh",NFILE,fnm);
1844 fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
1845 do_enxnms(fp,&nre,&enm);
1849 bVisco = opt2bSet("-vis",NFILE,fnm);
1851 if ((!bDisRe) && (!bDHDL))
1856 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
1857 for(j=0; j<nset; j++) {
1858 for(i=0; i<nre; i++) {
1859 if (strstr(enm[i].name,setnm[j])) {
1865 if (gmx_strcasecmp(setnm[j],"Volume")==0) {
1866 printf("Enter the box volume (" unit_volume "): ");
1867 if(1 != scanf("%lf",&dbl))
1869 gmx_fatal(FARGS,"Error reading user input");
1873 gmx_fatal(FARGS,"Could not find term %s for viscosity calculation",
1880 set=select_by_name(nre,enm,&nset);
1882 /* Print all the different units once */
1883 sprintf(buf,"(%s)",enm[set[0]].unit);
1884 for(i=1; i<nset; i++) {
1885 for(j=0; j<i; j++) {
1886 if (strcmp(enm[set[i]].unit,enm[set[j]].unit) == 0) {
1892 strcat(buf,enm[set[i]].unit);
1896 out=xvgropen(opt2fn("-o",NFILE,fnm),"Gromacs Energies","Time (ps)",buf,
1900 for(i=0; (i<nset); i++)
1901 leg[i] = enm[set[i]].name;
1903 leg[nset]=strdup("Sum");
1904 xvgr_legend(out,nset+1,(const char**)leg,oenv);
1907 xvgr_legend(out,nset,(const char**)leg,oenv);
1910 for(i=0; (i<nset); i++) {
1912 for (j=0; (j <= F_ETOT); j++)
1913 bIsEner[i] = bIsEner[i] ||
1914 (gmx_strcasecmp(interaction_function[j].longname,leg[i]) == 0);
1917 if (bPrAll && nset > 1) {
1918 gmx_fatal(FARGS,"Printing averages can only be done when a single set is selected");
1923 if (bORIRE || bOTEN)
1924 get_orires_parms(ftp2fn(efTPX,NFILE,fnm),&nor,&nex,&or_label,&oobs);
1937 fprintf(stderr,"Select the orientation restraint labels you want (-1 is all)\n");
1938 fprintf(stderr,"End your selection with 0\n");
1944 if(1 != scanf("%d",&(orsel[j])))
1946 gmx_fatal(FARGS,"Error reading user input");
1948 } while (orsel[j] > 0);
1949 if (orsel[0] == -1) {
1950 fprintf(stderr,"Selecting all %d orientation restraints\n",nor);
1953 for(i=0; i<nor; i++)
1956 /* Build the selection */
1958 for(i=0; i<j; i++) {
1959 for(k=0; k<nor; k++)
1960 if (or_label[k] == orsel[i]) {
1966 fprintf(stderr,"Orientation restraint label %d not found\n",
1970 snew(odtleg,norsel);
1971 for(i=0; i<norsel; i++) {
1972 snew(odtleg[i],256);
1973 sprintf(odtleg[i],"%d",or_label[orsel[i]]);
1976 fort=xvgropen(opt2fn("-ort",NFILE,fnm), "Calculated orientations",
1977 "Time (ps)","",oenv);
1979 fprintf(fort,"%s",orinst_sub);
1980 xvgr_legend(fort,norsel,(const char**)odtleg,oenv);
1983 fodt=xvgropen(opt2fn("-odt",NFILE,fnm),
1984 "Orientation restraint deviation",
1985 "Time (ps)","",oenv);
1987 fprintf(fodt,"%s",orinst_sub);
1988 xvgr_legend(fodt,norsel,(const char**)odtleg,oenv);
1993 foten=xvgropen(opt2fn("-oten",NFILE,fnm),
1994 "Order tensor","Time (ps)","",oenv);
1995 snew(otenleg,bOvec ? nex*12 : nex*3);
1996 for(i=0; i<nex; i++) {
1997 for(j=0; j<3; j++) {
1998 sprintf(buf,"eig%d",j+1);
1999 otenleg[(bOvec ? 12 : 3)*i+j] = strdup(buf);
2002 for(j=0; j<9; j++) {
2003 sprintf(buf,"vec%d%s",j/3+1,j%3==0 ? "x" : (j%3==1 ? "y" : "z"));
2004 otenleg[12*i+3+j] = strdup(buf);
2008 xvgr_legend(foten,bOvec ? nex*12 : nex*3,(const char**)otenleg,oenv);
2013 nbounds=get_bounds(ftp2fn(efTPX,NFILE,fnm),&bounds,&index,&pair,&npairs,
2015 snew(violaver,npairs);
2016 out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
2017 "Time (ps)","nm",oenv);
2018 xvgr_legend(out,2,drleg,oenv);
2020 fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
2021 "Time (ps)","Distance (nm)",oenv);
2022 if (output_env_get_print_xvgr_codes(oenv))
2023 fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
2027 get_dhdl_parms(ftp2fn(efTPX,NFILE,fnm),&ir);
2030 /* Initiate energies and set them to zero */
2039 /* Initiate counters */
2042 bFoundStart = FALSE;
2046 /* This loop searches for the first frame (when -b option is given),
2047 * or when this has been found it reads just one energy frame
2050 bCont = do_enx(fp,&(frame[NEXT]));
2052 timecheck = check_times(frame[NEXT].t);
2054 } while (bCont && (timecheck < 0));
2056 if ((timecheck == 0) && bCont) {
2057 /* We read a valid frame, so we can use it */
2058 fr = &(frame[NEXT]);
2061 /* The frame contains energies, so update cur */
2064 if (edat.nframes % 1000 == 0)
2066 srenew(edat.step,edat.nframes+1000);
2067 memset(&(edat.step[edat.nframes]),0,1000*sizeof(edat.step[0]));
2068 srenew(edat.steps,edat.nframes+1000);
2069 memset(&(edat.steps[edat.nframes]),0,1000*sizeof(edat.steps[0]));
2070 srenew(edat.points,edat.nframes+1000);
2071 memset(&(edat.points[edat.nframes]),0,1000*sizeof(edat.points[0]));
2073 for(i=0; i<nset; i++)
2075 srenew(edat.s[i].ener,edat.nframes+1000);
2076 memset(&(edat.s[i].ener[edat.nframes]),0,
2077 1000*sizeof(edat.s[i].ener[0]));
2078 srenew(edat.s[i].es ,edat.nframes+1000);
2079 memset(&(edat.s[i].es[edat.nframes]),0,
2080 1000*sizeof(edat.s[i].es[0]));
2085 edat.step[nfr] = fr->step;
2090 /* Initiate the previous step data */
2091 start_step = fr->step;
2093 /* Initiate the energy sums */
2094 edat.steps[nfr] = 1;
2095 edat.points[nfr] = 1;
2096 for(i=0; i<nset; i++)
2099 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2100 edat.s[i].es[nfr].sum2 = 0;
2107 edat.steps[nfr] = fr->nsteps;
2109 if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
2113 edat.points[nfr] = 1;
2114 for(i=0; i<nset; i++)
2117 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2118 edat.s[i].es[nfr].sum2 = 0;
2124 edat.points[nfr] = fr->nsum;
2125 for(i=0; i<nset; i++)
2128 edat.s[i].es[nfr].sum = fr->ener[sss].esum;
2129 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
2131 edat.npoints += fr->nsum;
2136 /* The interval does not match fr->nsteps:
2137 * can not do exact averages.
2141 edat.nsteps = fr->step - start_step + 1;
2144 for(i=0; i<nset; i++)
2146 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
2150 * Define distance restraint legends. Can only be done after
2151 * the first frame has been read... (Then we know how many there are)
2153 blk_disre=find_block_id_enxframe(fr, enxDISRE, NULL);
2154 if (bDisRe && bDRAll && !leg && blk_disre)
2159 fa = top->idef.il[F_DISRES].iatoms;
2160 ip = top->idef.iparams;
2161 if (blk_disre->nsub != 2 ||
2162 (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
2164 gmx_incons("Number of disre sub-blocks not equal to 2");
2167 ndisre=blk_disre->sub[0].nr ;
2168 if (ndisre != top->idef.il[F_DISRES].nr/3)
2170 gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
2171 ndisre,top->idef.il[F_DISRES].nr/3);
2173 snew(pairleg,ndisre);
2174 for(i=0; i<ndisre; i++)
2176 snew(pairleg[i],30);
2179 gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
2180 gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
2181 sprintf(pairleg[i],"%d %s %d %s (%d)",
2182 resnr_j,anm_j,resnr_k,anm_k,
2183 ip[fa[3*i]].disres.label);
2185 set=select_it(ndisre,pairleg,&nset);
2187 for(i=0; (i<nset); i++)
2190 sprintf(leg[2*i], "a %s",pairleg[set[i]]);
2191 snew(leg[2*i+1],32);
2192 sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
2194 xvgr_legend(fp_pairs,2*nset,(const char**)leg,oenv);
2198 * Store energies for analysis afterwards...
2200 if (!bDisRe && !bDHDL && (fr->nre > 0)) {
2201 if (edat.nframes % 1000 == 0) {
2202 srenew(time,edat.nframes+1000);
2204 time[edat.nframes] = fr->t;
2208 * Printing time, only when we do not want to skip frames
2210 if (!skip || teller % skip == 0) {
2212 /*******************************************
2213 * D I S T A N C E R E S T R A I N T S
2214 *******************************************/
2218 float *disre_rt = blk_disre->sub[0].fval;
2219 float *disre_rm3tav = blk_disre->sub[1].fval;
2221 double *disre_rt = blk_disre->sub[0].dval;
2222 double *disre_rm3tav = blk_disre->sub[1].dval;
2225 print_time(out,fr->t);
2226 if (violaver == NULL)
2227 snew(violaver,ndisre);
2229 /* Subtract bounds from distances, to calculate violations */
2230 calc_violations(disre_rt, disre_rm3tav,
2231 nbounds,pair,bounds,violaver,&sumt,&sumaver);
2233 fprintf(out," %8.4f %8.4f\n",sumaver,sumt);
2235 print_time(fp_pairs,fr->t);
2236 for(i=0; (i<nset); i++) {
2238 fprintf(fp_pairs," %8.4f", mypow(disre_rm3tav[sss],minthird));
2239 fprintf(fp_pairs," %8.4f", disre_rt[sss]);
2241 fprintf(fp_pairs,"\n");
2248 do_dhdl(fr, &ir, &fp_dhdl, opt2fn("-odh",NFILE,fnm), bDp, &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas, oenv);
2251 /*******************************************
2253 *******************************************/
2258 /* We skip frames with single points (usually only the first frame),
2259 * since they would result in an average plot with outliers.
2262 print_time(out,fr->t);
2263 print1(out,bDp,fr->ener[set[0]].e);
2264 print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
2265 print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
2271 print_time(out,fr->t);
2275 for(i=0; i<nset; i++)
2277 sum += fr->ener[set[i]].e;
2279 print1(out,bDp,sum/nmol-ezero);
2283 for(i=0; (i<nset); i++)
2287 print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
2291 print1(out,bDp,fr->ener[set[i]].e);
2298 blk = find_block_id_enxframe(fr, enx_i, NULL);
2302 xdr_datatype dt=xdr_datatype_float;
2304 xdr_datatype dt=xdr_datatype_double;
2308 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2310 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2313 vals=blk->sub[0].fval;
2315 vals=blk->sub[0].dval;
2318 if (blk->sub[0].nr != (size_t)nor)
2319 gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)", blk->sub[0].nr);
2322 for(i=0; i<nor; i++)
2323 orient[i] += vals[i];
2327 for(i=0; i<nor; i++)
2328 odrms[i] += sqr(vals[i]-oobs[i]);
2332 fprintf(fort," %10f",fr->t);
2333 for(i=0; i<norsel; i++)
2334 fprintf(fort," %g",vals[orsel[i]]);
2339 fprintf(fodt," %10f",fr->t);
2340 for(i=0; i<norsel; i++)
2341 fprintf(fodt," %g", vals[orsel[i]]-oobs[orsel[i]]);
2346 blk = find_block_id_enxframe(fr, enxORT, NULL);
2350 xdr_datatype dt=xdr_datatype_float;
2352 xdr_datatype dt=xdr_datatype_double;
2356 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2357 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2359 vals=blk->sub[0].fval;
2361 vals=blk->sub[0].dval;
2364 if (blk->sub[0].nr != (size_t)(nex*12))
2365 gmx_fatal(FARGS,"Number of orientation experiments in energy file (%g) does not match with the topology (%d)",
2366 blk->sub[0].nr/12, nex);
2367 fprintf(foten," %10f",fr->t);
2368 for(i=0; i<nex; i++)
2369 for(j=0; j<(bOvec?12:3); j++)
2370 fprintf(foten," %g",vals[i*12+j]);
2371 fprintf(foten,"\n");
2377 } while (bCont && (timecheck == 0));
2379 fprintf(stderr,"\n");
2393 out = xvgropen(opt2fn("-ora",NFILE,fnm),
2394 "Average calculated orientations",
2395 "Restraint label","",oenv);
2397 fprintf(out,"%s",orinst_sub);
2398 for(i=0; i<nor; i++)
2399 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr);
2403 out = xvgropen(opt2fn("-oda",NFILE,fnm),
2404 "Average restraint deviation",
2405 "Restraint label","",oenv);
2407 fprintf(out,"%s",orinst_sub);
2408 for(i=0; i<nor; i++)
2409 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr-oobs[i]);
2413 out = xvgropen(opt2fn("-odr",NFILE,fnm),
2414 "RMS orientation restraint deviations",
2415 "Restraint label","",oenv);
2417 fprintf(out,"%s",orinst_sub);
2418 for(i=0; i<nor; i++)
2419 fprintf(out,"%5d %g\n",or_label[i],sqrt(odrms[i]/norfr));
2427 analyse_disre(opt2fn("-viol",NFILE,fnm),
2428 teller_disre,violaver,bounds,index,pair,nbounds,oenv);
2435 printf("\n\nWrote %d lambda values with %d samples as ",
2436 dh_lambdas, dh_samples);
2439 printf("%d dH histograms ", dh_hists);
2443 printf("%d dH data blocks ", dh_blocks);
2445 printf("to %s\n", opt2fn("-odh",NFILE,fnm));
2450 gmx_fatal(FARGS, "No dH data in %s\n", opt2fn("-f",NFILE,fnm));
2456 double dt = (frame[cur].t-start_t)/(edat.nframes-1);
2457 analyse_ener(opt2bSet("-corr",NFILE,fnm),opt2fn("-corr",NFILE,fnm),
2458 bFee,bSum,bFluct,opt2parg_bSet("-nmol",npargs,ppa),
2459 bVisco,opt2fn("-vis",NFILE,fnm),
2461 start_step,start_t,frame[cur].step,frame[cur].t,
2463 nset,set,bIsEner,leg,enm,Vaver,ezero,nbmin,nbmax,
2466 calc_fluctuation_props(stdout,bDriftCorr,dt,nset,set,nmol,leg,&edat,
2469 if (opt2bSet("-f2",NFILE,fnm)) {
2470 fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
2471 reftemp, nset, set, leg, &edat, time ,oenv);
2475 const char *nxy = "-nxy";
2477 do_view(oenv,opt2fn("-o",NFILE,fnm),nxy);
2478 do_view(oenv,opt2fn_null("-ravg",NFILE,fnm),nxy);
2479 do_view(oenv,opt2fn_null("-ora",NFILE,fnm),nxy);
2480 do_view(oenv,opt2fn_null("-ort",NFILE,fnm),nxy);
2481 do_view(oenv,opt2fn_null("-oda",NFILE,fnm),nxy);
2482 do_view(oenv,opt2fn_null("-odr",NFILE,fnm),nxy);
2483 do_view(oenv,opt2fn_null("-odt",NFILE,fnm),nxy);
2484 do_view(oenv,opt2fn_null("-oten",NFILE,fnm),nxy);
2485 do_view(oenv,opt2fn_null("-odh",NFILE,fnm),nxy);