1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * Green Red Orange Magenta Azure Cyan Skyblue
45 #include "gmx_fatal.h"
59 #include "mtop_util.h"
63 static real minthird=-1.0/3.0,minsixth=-1.0/6.0;
81 gmx_large_int_t nsteps;
82 gmx_large_int_t npoints;
90 static double mypow(double x,double y)
98 static int *select_it(int nre,char *nm[],int *nset)
103 gmx_bool bVerbose = TRUE;
105 if ((getenv("VERBOSE")) != NULL)
108 fprintf(stderr,"Select the terms you want from the following list\n");
109 fprintf(stderr,"End your selection with 0\n");
112 for(k=0; (k<nre); ) {
113 for(j=0; (j<4) && (k<nre); j++,k++)
114 fprintf(stderr," %3d=%14s",k+1,nm[k]);
115 fprintf(stderr,"\n");
121 if(1 != scanf("%d",&n))
123 gmx_fatal(FARGS,"Error reading user input");
125 if ((n>0) && (n<=nre))
130 for(i=(*nset)=0; (i<nre); i++)
139 static int strcount(const char *s1,const char *s2)
142 while (s1 && s2 && (toupper(s1[n]) == toupper(s2[n])))
147 static void chomp(char *buf)
149 int len = strlen(buf);
151 while ((len > 0) && (buf[len-1] == '\n')) {
157 static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
160 int n,k,kk,j,i,nmatch,nind,nss;
162 gmx_bool bEOF,bVerbose = TRUE,bLong=FALSE;
163 char *ptr,buf[STRLEN];
164 const char *fm4="%3d %-14s";
165 const char *fm2="%3d %-34s";
168 if ((getenv("VERBOSE")) != NULL)
171 fprintf(stderr,"\n");
172 fprintf(stderr,"Select the terms you want from the following list by\n");
173 fprintf(stderr,"selecting either (part of) the name or the number or a combination.\n");
174 fprintf(stderr,"End your selection with an empty line or a zero.\n");
175 fprintf(stderr,"-------------------------------------------------------------------\n");
179 for(k=0; k<nre; k++) {
180 newnm[k] = strdup(nm[k].name);
181 /* Insert dashes in all the names */
182 while ((ptr = strchr(newnm[k],' ')) != NULL) {
188 fprintf(stderr,"\n");
191 for(kk=k; kk<k+4; kk++) {
192 if (kk < nre && strlen(nm[kk].name) > 14) {
200 fprintf(stderr,fm4,k+1,newnm[k]);
206 fprintf(stderr,fm2,k+1,newnm[k]);
215 fprintf(stderr,"\n\n");
221 while (!bEOF && (fgets2(buf,STRLEN-1,stdin))) {
222 /* Remove newlines */
228 /* Empty line means end of input */
229 bEOF = (strlen(buf) == 0);
234 /* First try to read an integer */
235 nss = sscanf(ptr,"%d",&nind);
237 /* Zero means end of input */
240 } else if ((1<=nind) && (nind<=nre)) {
243 fprintf(stderr,"number %d is out of range\n",nind);
247 /* Now try to read a string */
250 for(nind=0; nind<nre; nind++) {
251 if (gmx_strcasecmp(newnm[nind],ptr) == 0) {
259 for(nind=0; nind<nre; nind++) {
260 if (gmx_strncasecmp(newnm[nind],ptr,i) == 0) {
266 fprintf(stderr,"String '%s' does not match anything\n",ptr);
271 /* Look for the first space, and remove spaces from there */
272 if ((ptr = strchr(ptr,' ')) != NULL) {
275 } while (!bEOF && (ptr && (strlen(ptr) > 0)));
280 for(i=(*nset)=0; (i<nre); i++)
287 gmx_fatal(FARGS,"No energy terms selected");
289 for(i=0; (i<nre); i++)
296 static void get_orires_parms(const char *topnm,
297 int *nor,int *nex,int **label,real **obs)
308 read_tpx(topnm,&ir,box,&natoms,NULL,NULL,NULL,&mtop);
309 top = gmx_mtop_generate_local_top(&mtop,&ir);
311 ip = top->idef.iparams;
312 iatom = top->idef.il[F_ORIRES].iatoms;
314 /* Count how many distance restraint there are... */
315 nb = top->idef.il[F_ORIRES].nr;
317 gmx_fatal(FARGS,"No orientation restraints in topology!\n");
323 for(i=0; i<nb; i+=3) {
324 (*label)[i/3] = ip[iatom[i]].orires.label;
325 (*obs)[i/3] = ip[iatom[i]].orires.obs;
326 if (ip[iatom[i]].orires.ex >= *nex)
327 *nex = ip[iatom[i]].orires.ex+1;
329 fprintf(stderr,"Found %d orientation restraints with %d experiments",
333 static int get_bounds(const char *topnm,
334 real **bounds,int **index,int **dr_pair,int *npairs,
335 gmx_mtop_t *mtop,gmx_localtop_t **ltop,t_inputrec *ir)
338 t_functype *functype;
340 int natoms,i,j,k,type,ftype,natom;
348 read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,mtop);
350 top = gmx_mtop_generate_local_top(mtop,ir);
353 functype = top->idef.functype;
354 ip = top->idef.iparams;
356 /* Count how many distance restraint there are... */
357 nb=top->idef.il[F_DISRES].nr;
359 gmx_fatal(FARGS,"No distance restraints in topology!\n");
361 /* Allocate memory */
366 /* Fill the bound array */
368 for(i=0; (i<top->idef.ntypes); i++) {
370 if (ftype == F_DISRES) {
372 label1 = ip[i].disres.label;
373 b[nb] = ip[i].disres.up1;
380 /* Fill the index array */
382 disres = &(top->idef.il[F_DISRES]);
383 iatom = disres->iatoms;
384 for(i=j=k=0; (i<disres->nr); ) {
386 ftype = top->idef.functype[type];
387 natom = interaction_function[ftype].nratoms+1;
388 if (label1 != top->idef.iparams[type].disres.label) {
390 label1 = top->idef.iparams[type].disres.label;
399 gmx_incons("get_bounds for distance restraints");
407 static void calc_violations(real rt[],real rav3[],int nb,int index[],
408 real bounds[],real *viol,double *st,double *sa)
410 const real sixth=1.0/6.0;
412 double rsum,rav,sumaver,sumt;
416 for(i=0; (i<nb); i++) {
419 for(j=index[i]; (j<index[i+1]); j++) {
421 viol[j] += mypow(rt[j],-3.0);
423 rsum += mypow(rt[j],-6);
425 rsum = max(0.0,mypow(rsum,-sixth)-bounds[i]);
426 rav = max(0.0,mypow(rav, -sixth)-bounds[i]);
435 static void analyse_disre(const char *voutfn, int nframes,
436 real violaver[], real bounds[], int index[],
437 int pair[], int nbounds,
438 const output_env_t oenv)
441 double sum,sumt,sumaver;
444 /* Subtract bounds from distances, to calculate violations */
445 calc_violations(violaver,violaver,
446 nbounds,pair,bounds,NULL,&sumt,&sumaver);
449 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
451 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",
454 vout=xvgropen(voutfn,"r\\S-3\\N average violations","DR Index","nm",
458 for(i=0; (i<nbounds); i++) {
459 /* Do ensemble averaging */
461 for(j=pair[i]; (j<pair[i+1]); j++)
462 sumaver += sqr(violaver[j]/nframes);
463 sumaver = max(0.0,mypow(sumaver,minsixth)-bounds[i]);
466 sum = max(sum,sumaver);
467 fprintf(vout,"%10d %10.5e\n",index[i],sumaver);
470 for(j=0; (j<dr.ndr); j++)
471 fprintf(vout,"%10d %10.5e\n",j,mypow(violaver[j]/nframes,minthird));
475 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
477 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",sum);
479 do_view(oenv,voutfn,"-graphtype bar");
482 static void einstein_visco(const char *fn,const char *fni,int nsets,
483 int nframes,real **sum,
484 real V,real T,int nsteps,double time[],
485 const output_env_t oenv)
488 double av[4],avold[4];
495 dt = (time[1]-time[0]);
498 for(i=0; i<=nsets; i++)
500 fp0=xvgropen(fni,"Shear viscosity integral",
501 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N ps)",oenv);
502 fp1=xvgropen(fn,"Shear viscosity using Einstein relation",
503 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N)",oenv);
504 for(i=1; i<nf4; i++) {
505 fac = dt*nframes/nsteps;
506 for(m=0; m<=nsets; m++)
508 for(j=0; j<nframes-i; j++) {
509 for(m=0; m<nsets; m++) {
510 di = sqr(fac*(sum[m][j+i]-sum[m][j]));
513 av[nsets] += di/nsets;
516 /* Convert to SI for the viscosity */
517 fac = (V*NANO*NANO*NANO*PICO*1e10)/(2*BOLTZMANN*T)/(nframes-i);
518 fprintf(fp0,"%10g",time[i]-time[0]);
519 for(m=0; (m<=nsets); m++) {
521 fprintf(fp0," %10g",av[m]);
524 fprintf(fp1,"%10g",0.5*(time[i]+time[i-1])-time[0]);
525 for(m=0; (m<=nsets); m++) {
526 fprintf(fp1," %10g",(av[m]-avold[m])/dt);
546 gmx_large_int_t nst_min;
549 static void clear_ee_sum(ee_sum_t *ees)
557 static void add_ee_sum(ee_sum_t *ees,double sum,int np)
563 static void add_ee_av(ee_sum_t *ees)
567 av = ees->sum/ees->np;
574 static double calc_ee2(int nb,ee_sum_t *ees)
576 return (ees->sav2/nb - dsqr(ees->sav/nb))/(nb - 1);
579 static void set_ee_av(ener_ee_t *eee)
583 char buf[STEPSTRSIZE];
584 fprintf(debug,"Storing average for err.est.: %s steps\n",
585 gmx_step_str(eee->nst,buf));
587 add_ee_av(&eee->sum);
589 if (eee->b == 1 || eee->nst < eee->nst_min)
591 eee->nst_min = eee->nst;
596 static void calc_averages(int nset,enerdata_t *edat,int nbmin,int nbmax)
599 double sum,sum2,sump,see2;
600 gmx_large_int_t steps,np,p,bound_nb;
604 double x,sx,sy,sxx,sxy;
607 /* Check if we have exact statistics over all points */
608 for(i=0; i<nset; i++)
611 ed->bExactStat = FALSE;
612 if (edat->npoints > 0)
614 /* All energy file sum entries 0 signals no exact sums.
615 * But if all energy values are 0, we still have exact sums.
618 for(f=0; f<edat->nframes && !ed->bExactStat; f++)
620 if (ed->ener[i] != 0)
624 ed->bExactStat = (ed->es[f].sum != 0);
628 ed->bExactStat = TRUE;
634 for(i=0; i<nset; i++)
645 for(nb=nbmin; nb<=nbmax; nb++)
648 clear_ee_sum(&eee[nb].sum);
652 for(f=0; f<edat->nframes; f++)
658 /* Add the sum and the sum of variances to the totals. */
664 sum2 += dsqr(sum/np - (sum + es->sum)/(np + p))
670 /* Add a single value to the sum and sum of squares. */
676 /* sum has to be increased after sum2 */
680 /* For the linear regression use variance 1/p.
681 * Note that sump is the sum, not the average, so we don't need p*.
683 x = edat->step[f] - 0.5*(edat->steps[f] - 1);
689 for(nb=nbmin; nb<=nbmax; nb++)
691 /* Check if the current end step is closer to the desired
692 * block boundary than the next end step.
694 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
695 if (eee[nb].nst > 0 &&
696 bound_nb - edat->step[f-1]*nb < edat->step[f]*nb - bound_nb)
706 eee[nb].nst += edat->step[f] - edat->step[f-1];
710 add_ee_sum(&eee[nb].sum,es->sum,edat->points[f]);
714 add_ee_sum(&eee[nb].sum,edat->s[i].ener[f],1);
716 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
717 if (edat->step[f]*nb >= bound_nb)
724 edat->s[i].av = sum/np;
727 edat->s[i].rmsd = sqrt(sum2/np);
731 edat->s[i].rmsd = sqrt(sum2/np - dsqr(edat->s[i].av));
734 if (edat->nframes > 1)
736 edat->s[i].slope = (np*sxy - sx*sy)/(np*sxx - sx*sx);
740 edat->s[i].slope = 0;
745 for(nb=nbmin; nb<=nbmax; nb++)
747 /* Check if we actually got nb blocks and if the smallest
748 * block is not shorter than 80% of the average.
752 char buf1[STEPSTRSIZE],buf2[STEPSTRSIZE];
753 fprintf(debug,"Requested %d blocks, we have %d blocks, min %s nsteps %s\n",
755 gmx_step_str(eee[nb].nst_min,buf1),
756 gmx_step_str(edat->nsteps,buf2));
758 if (eee[nb].b == nb && 5*nb*eee[nb].nst_min >= 4*edat->nsteps)
760 see2 += calc_ee2(nb,&eee[nb].sum);
766 edat->s[i].ee = sqrt(see2/nee);
776 static enerdata_t *calc_sum(int nset,enerdata_t *edat,int nbmin,int nbmax)
787 snew(s->ener,esum->nframes);
788 snew(s->es ,esum->nframes);
790 s->bExactStat = TRUE;
792 for(i=0; i<nset; i++)
794 if (!edat->s[i].bExactStat)
796 s->bExactStat = FALSE;
798 s->slope += edat->s[i].slope;
801 for(f=0; f<edat->nframes; f++)
804 for(i=0; i<nset; i++)
806 sum += edat->s[i].ener[f];
810 for(i=0; i<nset; i++)
812 sum += edat->s[i].es[f].sum;
818 calc_averages(1,esum,nbmin,nbmax);
823 static char *ee_pr(double ee,char *buf)
830 sprintf(buf,"%s","--");
834 /* Round to two decimals by printing. */
835 sprintf(tmp,"%.1e",ee);
836 sscanf(tmp,"%lf",&rnd);
837 sprintf(buf,"%g",rnd);
843 static void remove_drift(int nset,int nbmin,int nbmax,real dt,enerdata_t *edat)
845 /* Remove the drift by performing a fit to y = ax+b.
846 Uses 5 iterations. */
848 double delta,d,sd,sd2;
850 edat->npoints = edat->nframes;
851 edat->nsteps = edat->nframes;
855 for(i=0; (i<nset); i++)
857 delta = edat->s[i].slope*dt;
860 fprintf(debug,"slope for set %d is %g\n",i,edat->s[i].slope);
862 for(j=0; (j<edat->nframes); j++)
864 edat->s[i].ener[j] -= j*delta;
865 edat->s[i].es[j].sum = 0;
866 edat->s[i].es[j].sum2 = 0;
869 calc_averages(nset,edat,nbmin,nbmax);
873 static void calc_fluctuation_props(FILE *fp,
874 gmx_bool bDriftCorr,real dt,
875 int nset,int set[],int nmol,
876 char **leg,enerdata_t *edat,
880 double vvhh,vv,v,h,hh2,vv2,varv,hh,varh,tt,cv,cp,alpha,kappa,dcp,et,varet;
882 enum { eVol, eEnth, eTemp, eEtot, eNR };
883 const char *my_ener[] = { "Volume", "Enthalpy", "Temperature", "Total Energy" };
886 NANO3 = NANO*NANO*NANO;
889 fprintf(fp,"\nYou may want to use the -driftcorr flag in order to correct\n"
890 "for spurious drift in the graphs. Note that this is not\n"
891 "a substitute for proper equilibration and sampling!\n");
895 remove_drift(nset,nbmin,nbmax,dt,edat);
897 for(i=0; (i<eNR); i++)
899 for(ii[i]=0; (ii[i]<nset &&
900 (gmx_strcasecmp(leg[ii[i]],my_ener[i]) != 0)); ii[i]++)
903 fprintf(fp,"Found %s data.\n",my_ener[i]);
905 /* Compute it all! */
906 vvhh = alpha = kappa = cp = dcp = cv = NOTSET;
910 if (ii[eTemp] < nset)
912 tt = edat->s[ii[eTemp]].av;
916 if ((ii[eVol] < nset) && (ii[eTemp] < nset))
918 vv = edat->s[ii[eVol]].av*NANO3;
919 varv = dsqr(edat->s[ii[eVol]].rmsd*NANO3);
920 kappa = (varv/vv)/(BOLTZMANN*tt);
924 if ((ii[eEnth] < nset) && (ii[eTemp] < nset))
926 hh = KILO*edat->s[ii[eEnth]].av/AVOGADRO;
927 varh = dsqr(KILO*edat->s[ii[eEnth]].rmsd/AVOGADRO);
928 cp = AVOGADRO*((varh/nmol)/(BOLTZMANN*tt*tt));
932 if ((ii[eEtot] < nset) && (hh == NOTSET) && (tt != NOTSET))
934 /* Only compute cv in constant volume runs, which we can test
935 by checking whether the enthalpy was computed.
937 et = edat->s[ii[eEtot]].av;
938 varet = sqr(edat->s[ii[eEtot]].rmsd);
939 cv = KILO*((varet/nmol)/(BOLTZ*tt*tt));
942 if ((ii[eVol] < nset) && (ii[eEnth] < nset) && (ii[eTemp] < nset))
945 for(j=0; (j<edat->nframes); j++)
947 v = edat->s[ii[eVol]].ener[j]*NANO3;
948 h = KILO*edat->s[ii[eEnth]].ener[j]/AVOGADRO;
951 vvhh /= edat->nframes;
952 alpha = (vvhh-vv*hh)/(vv*BOLTZMANN*tt*tt);
953 dcp = (vv*AVOGADRO/nmol)*tt*sqr(alpha)/(kappa);
959 fprintf(fp,"\nWARNING: nmol = %d, this may not be what you want.\n",
961 fprintf(fp,"\nTemperature dependent fluctuation properties at T = %g.\n",tt);
962 fprintf(fp,"\nHeat capacities obtained from fluctuations do *not* include\n");
963 fprintf(fp,"quantum corrections. If you want to get a more accurate estimate\n");
964 fprintf(fp,"please use the g_dos program.\n\n");
965 fprintf(fp,"WARNING: Please verify that your simulations are converged and perform\n"
966 "a block-averaging error analysis (not implemented in g_energy yet)\n");
971 fprintf(fp,"varv = %10g (m^6)\n",varv*AVOGADRO/nmol);
973 fprintf(fp,"vvhh = %10g (m^3 J)\n",vvhh);
976 fprintf(fp,"Volume = %10g m^3/mol\n",
979 fprintf(fp,"Enthalpy = %10g kJ/mol\n",
980 hh*AVOGADRO/(KILO*nmol));
982 fprintf(fp,"Coefficient of Thermal Expansion Alpha_P = %10g (1/K)\n",
986 fprintf(fp,"Isothermal Compressibility Kappa = %10g (J/m^3)\n",
988 fprintf(fp,"Adiabatic bulk modulus = %10g (m^3/J)\n",
992 fprintf(fp,"Heat capacity at constant pressure Cp = %10g J/mol K\n",
995 fprintf(fp,"Heat capacity at constant volume Cv = %10g J/mol K\n",
998 fprintf(fp,"Cp-Cv = %10g J/mol K\n",
1000 please_cite(fp,"Allen1987a");
1004 fprintf(fp,"You should select the temperature in order to obtain fluctuation properties.\n");
1008 static void analyse_ener(gmx_bool bCorr,const char *corrfn,
1009 gmx_bool bFee,gmx_bool bSum,gmx_bool bFluct,gmx_bool bTempFluct,
1010 gmx_bool bVisco,const char *visfn,int nmol,
1011 gmx_large_int_t start_step,double start_t,
1012 gmx_large_int_t step,double t,
1013 double time[], real reftemp,
1015 int nset,int set[],gmx_bool *bIsEner,
1016 char **leg,gmx_enxnm_t *enm,
1017 real Vaver,real ezero,
1018 int nbmin,int nbmax,
1019 const output_env_t oenv)
1022 /* Check out the printed manual for equations! */
1023 double Dt,aver,stddev,errest,delta_t,totaldrift;
1024 enerdata_t *esum=NULL;
1025 real xxx,integral,intBulk,Temp=0,Pres=0;
1026 real sfrac,oldfrac,diffsum,diffav,fstep,pr_aver,pr_stddev,pr_errest;
1027 double beta=0,expE,expEtot,*fee=NULL;
1028 gmx_large_int_t nsteps;
1029 int nexact,nnotexact;
1033 char buf[256],eebuf[100];
1035 nsteps = step - start_step + 1;
1037 fprintf(stdout,"Not enough steps (%s) for statistics\n",
1038 gmx_step_str(nsteps,buf));
1041 /* Calculate the time difference */
1042 delta_t = t - start_t;
1044 fprintf(stdout,"\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
1045 gmx_step_str(nsteps,buf),start_t,t,nset);
1047 calc_averages(nset,edat,nbmin,nbmax);
1050 esum = calc_sum(nset,edat,nbmin,nbmax);
1053 if (edat->npoints == 0) {
1059 for(i=0; (i<nset); i++) {
1060 if (edat->s[i].bExactStat) {
1068 if (nnotexact == 0) {
1069 fprintf(stdout,"All statistics are over %s points\n",
1070 gmx_step_str(edat->npoints,buf));
1071 } else if (nexact == 0 || edat->npoints == edat->nframes) {
1072 fprintf(stdout,"All statistics are over %d points (frames)\n",
1075 fprintf(stdout,"The term%s",nnotexact==1 ? "" : "s");
1076 for(i=0; (i<nset); i++) {
1077 if (!edat->s[i].bExactStat) {
1078 fprintf(stdout," '%s'",leg[i]);
1081 fprintf(stdout," %s has statistics over %d points (frames)\n",
1082 nnotexact==1 ? "is" : "are",edat->nframes);
1083 fprintf(stdout,"All other statistics are over %s points\n",
1084 gmx_step_str(edat->npoints,buf));
1086 fprintf(stdout,"\n");
1088 fprintf(stdout,"%-24s %10s %10s %10s %10s",
1089 "Energy","Average","Err.Est.","RMSD","Tot-Drift");
1091 fprintf(stdout," %10s\n","-kT ln<e^(E/kT)>");
1093 fprintf(stdout,"\n");
1094 fprintf(stdout,"-------------------------------------------------------------------------------\n");
1096 /* Initiate locals, only used with -sum */
1099 beta = 1.0/(BOLTZ*reftemp);
1102 for(i=0; (i<nset); i++) {
1103 aver = edat->s[i].av;
1104 stddev = edat->s[i].rmsd;
1105 errest = edat->s[i].ee;
1109 for(j=0; (j<edat->nframes); j++) {
1110 expE += exp(beta*(edat->s[i].ener[j] - aver)/nmol);
1113 expEtot+=expE/edat->nframes;
1115 fee[i] = log(expE/edat->nframes)/beta + aver/nmol;
1117 if (strstr(leg[i],"empera") != NULL) {
1119 } else if (strstr(leg[i],"olum") != NULL) {
1121 } else if (strstr(leg[i],"essure") != NULL) {
1125 pr_aver = aver/nmol-ezero;
1126 pr_stddev = stddev/nmol;
1127 pr_errest = errest/nmol;
1135 /* Multiply the slope in steps with the number of steps taken */
1136 totaldrift = (edat->nsteps - 1)*edat->s[i].slope;
1142 fprintf(stdout,"%-24s %10g %10s %10g %10g",
1143 leg[i],pr_aver,ee_pr(pr_errest,eebuf),pr_stddev,totaldrift);
1145 fprintf(stdout," %10g",fee[i]);
1147 fprintf(stdout," (%s)\n",enm[set[i]].unit);
1150 for(j=0; (j<edat->nframes); j++)
1151 edat->s[i].ener[j] -= aver;
1155 totaldrift = (edat->nsteps - 1)*esum->s[0].slope;
1156 fprintf(stdout,"%-24s %10g %10s %10s %10g (%s)",
1157 "Total",esum->s[0].av/nmol,ee_pr(esum->s[0].ee/nmol,eebuf),
1158 "--",totaldrift/nmol,enm[set[0]].unit);
1159 /* pr_aver,pr_stddev,a,totaldrift */
1161 fprintf(stdout," %10g %10g\n",
1162 log(expEtot)/beta + esum->s[0].av/nmol,log(expEtot)/beta);
1164 fprintf(stdout,"\n");
1167 /* Do correlation function */
1168 if (edat->nframes > 1)
1170 Dt = delta_t/(edat->nframes - 1);
1177 const char* leg[] = { "Shear", "Bulk" };
1182 /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
1184 /* Symmetrise tensor! (and store in first three elements)
1185 * And subtract average pressure!
1188 for(i=0; i<12; i++) {
1189 snew(eneset[i],edat->nframes);
1192 for(i=0; i<3; i++) {
1193 snew(enesum[i],edat->nframes);
1195 for(i=0; (i<edat->nframes); i++) {
1196 eneset[0][i] = 0.5*(edat->s[1].ener[i]+edat->s[3].ener[i]);
1197 eneset[1][i] = 0.5*(edat->s[2].ener[i]+edat->s[6].ener[i]);
1198 eneset[2][i] = 0.5*(edat->s[5].ener[i]+edat->s[7].ener[i]);
1199 for(j=3; j<=11; j++) {
1200 eneset[j][i] = edat->s[j].ener[i];
1202 eneset[11][i] -= Pres;
1203 enesum[0][i] = 0.5*(edat->s[1].es[i].sum+edat->s[3].es[i].sum);
1204 enesum[1][i] = 0.5*(edat->s[2].es[i].sum+edat->s[6].es[i].sum);
1205 enesum[2][i] = 0.5*(edat->s[5].es[i].sum+edat->s[7].es[i].sum);
1208 einstein_visco("evisco.xvg","eviscoi.xvg",
1209 3,edat->nframes,enesum,Vaver,Temp,nsteps,time,oenv);
1211 /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
1212 /* Do it for shear viscosity */
1213 strcpy(buf,"Shear Viscosity");
1214 low_do_autocorr(corrfn,oenv,buf,edat->nframes,3,
1215 (edat->nframes+1)/2,eneset,Dt,
1216 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1218 /* Now for bulk viscosity */
1219 strcpy(buf,"Bulk Viscosity");
1220 low_do_autocorr(corrfn,oenv,buf,edat->nframes,1,
1221 (edat->nframes+1)/2,&(eneset[11]),Dt,
1222 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1224 factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
1225 fp=xvgropen(visfn,buf,"Time (ps)","\\8h\\4 (cp)",oenv);
1226 xvgr_legend(fp,asize(leg),leg,oenv);
1228 /* Use trapezium rule for integration */
1231 nout = get_acfnout();
1232 if ((nout < 2) || (nout >= edat->nframes/2))
1233 nout = edat->nframes/2;
1234 for(i=1; (i<nout); i++)
1236 integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
1237 intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
1238 fprintf(fp,"%10g %10g %10g\n",(i*Dt),integral,intBulk);
1244 strcpy(buf,"Autocorrelation of Energy Fluctuations");
1246 strcpy(buf,"Energy Autocorrelation");
1248 do_autocorr(corrfn,oenv,buf,edat->nframes,
1250 bSum ? &edat->s[nset-1].ener : eneset,
1251 (delta_t/edat->nframes),eacNormal,FALSE);
1257 static void print_time(FILE *fp,double t)
1259 fprintf(fp,"%12.6f",t);
1262 static void print1(FILE *fp,gmx_bool bDp,real e)
1265 fprintf(fp," %16.12f",e);
1267 fprintf(fp," %10.6f",e);
1270 static void fec(const char *ene2fn, const char *runavgfn,
1271 real reftemp, int nset, int set[], char *leg[],
1272 enerdata_t *edat, double time[],
1273 const output_env_t oenv)
1275 const char* ravgleg[] = { "\\8D\\4E = E\\sB\\N-E\\sA\\N",
1276 "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N" };
1279 int nre,timecheck,step,nenergy,nenergy2,maxenergy;
1285 gmx_enxnm_t *enm=NULL;
1289 /* read second energy file */
1292 enx = open_enx(ene2fn,"r");
1293 do_enxnms(enx,&(fr->nre),&enm);
1295 snew(eneset2,nset+1);
1300 /* This loop searches for the first frame (when -b option is given),
1301 * or when this has been found it reads just one energy frame
1304 bCont = do_enx(enx,fr);
1307 timecheck = check_times(fr->t);
1309 } while (bCont && (timecheck < 0));
1311 /* Store energies for analysis afterwards... */
1312 if ((timecheck == 0) && bCont) {
1314 if ( nenergy2 >= maxenergy ) {
1316 for(i=0; i<=nset; i++)
1317 srenew(eneset2[i],maxenergy);
1319 if (fr->t != time[nenergy2])
1320 fprintf(stderr,"\nWARNING time mismatch %g!=%g at frame %s\n",
1321 fr->t, time[nenergy2], gmx_step_str(fr->step,buf));
1322 for(i=0; i<nset; i++)
1323 eneset2[i][nenergy2] = fr->ener[set[i]].e;
1327 } while (bCont && (timecheck == 0));
1330 if (edat->nframes != nenergy2) {
1331 fprintf(stderr,"\nWARNING file length mismatch %d!=%d\n",
1332 edat->nframes,nenergy2);
1334 nenergy = min(edat->nframes,nenergy2);
1336 /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
1339 fp=xvgropen(runavgfn,"Running average free energy difference",
1340 "Time (" unit_time ")","\\8D\\4E (" unit_energy ")",oenv);
1341 xvgr_legend(fp,asize(ravgleg),ravgleg,oenv);
1343 fprintf(stdout,"\n%-24s %10s\n",
1344 "Energy","dF = -kT ln < exp(-(EB-EA)/kT) >A");
1346 beta = 1.0/(BOLTZ*reftemp);
1347 for(i=0; i<nset; i++) {
1348 if (gmx_strcasecmp(leg[i],enm[set[i]].name)!=0)
1349 fprintf(stderr,"\nWARNING energy set name mismatch %s!=%s\n",
1350 leg[i],enm[set[i]].name);
1351 for(j=0; j<nenergy; j++) {
1352 dE = eneset2[i][j] - edat->s[i].ener[j];
1353 sum += exp(-dE*beta);
1355 fprintf(fp,"%10g %10g %10g\n",
1356 time[j], dE, -BOLTZ*reftemp*log(sum/(j+1)) );
1358 aver = -BOLTZ*reftemp*log(sum/nenergy);
1359 fprintf(stdout,"%-24s %10g\n",leg[i],aver);
1366 static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
1367 int *blocks, int *hists, int *samples, int *nlambdas,
1368 const output_env_t oenv)
1370 const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
1371 char title[STRLEN],label_x[STRLEN],label_y[STRLEN], legend[STRLEN];
1373 gmx_bool first=FALSE;
1374 int nblock_hist=0, nblock_dh=0, nblock_dhcoll=0;
1377 double temp=0, start_time=0, delta_time=0, start_lambda=0, delta_lambda=0;
1379 gmx_bool changing_lambda=FALSE;
1381 /* now count the blocks & handle the global dh data */
1382 for(i=0;i<fr->nblock;i++)
1384 if (fr->block[i].id == enxDHHIST)
1388 else if (fr->block[i].id == enxDH)
1392 else if (fr->block[i].id == enxDHCOLL)
1395 if ( (fr->block[i].nsub < 1) ||
1396 (fr->block[i].sub[0].type != xdr_datatype_double) ||
1397 (fr->block[i].sub[0].nr < 5))
1399 gmx_fatal(FARGS, "Unexpected block data");
1402 /* read the data from the DHCOLL block */
1403 temp = fr->block[i].sub[0].dval[0];
1404 start_time = fr->block[i].sub[0].dval[1];
1405 delta_time = fr->block[i].sub[0].dval[2];
1406 start_lambda = fr->block[i].sub[0].dval[3];
1407 delta_lambda = fr->block[i].sub[0].dval[4];
1408 changing_lambda = (delta_lambda != 0);
1412 if (nblock_hist == 0 && nblock_dh == 0)
1414 /* don't do anything */
1417 if (nblock_hist>0 && nblock_dh>0)
1419 gmx_fatal(FARGS, "This energy file contains both histogram dhdl data and non-histogram dhdl data. Don't know what to do.");
1425 sprintf(title,"%s, %s",dhdl,deltag);
1426 sprintf(label_x,"%s (%s)","Time",unit_time);
1427 sprintf(label_y,"(%s)",unit_energy);
1431 sprintf(title,"N(%s)",deltag);
1432 sprintf(label_x,"%s (%s)",deltag,unit_energy);
1433 sprintf(label_y,"Samples");
1435 *fp_dhdl=xvgropen_type(filename, title, label_x, label_y, exvggtXNY,
1437 if (! changing_lambda)
1439 sprintf(buf,"T = %g (K), %s = %g", temp, lambda, start_lambda);
1443 sprintf(buf,"T = %g (K)", temp);
1445 xvgr_subtitle(*fp_dhdl,buf,oenv);
1451 (*hists)+=nblock_hist;
1452 (*blocks)+=nblock_dh;
1453 (*nlambdas) = nblock_hist+nblock_dh;
1456 /* write the data */
1457 if (nblock_hist > 0)
1459 gmx_large_int_t sum=0;
1461 for(i=0;i<fr->nblock;i++)
1463 t_enxblock *blk=&(fr->block[i]);
1464 if (blk->id==enxDHHIST)
1466 double foreign_lambda, dx;
1468 int nhist, derivative;
1470 /* check the block types etc. */
1471 if ( (blk->nsub < 2) ||
1472 (blk->sub[0].type != xdr_datatype_double) ||
1473 (blk->sub[1].type != xdr_datatype_large_int) ||
1474 (blk->sub[0].nr < 2) ||
1475 (blk->sub[1].nr < 2) )
1477 gmx_fatal(FARGS, "Unexpected block data in file");
1479 foreign_lambda=blk->sub[0].dval[0];
1480 dx=blk->sub[0].dval[1];
1481 nhist=blk->sub[1].lval[0];
1482 derivative=blk->sub[1].lval[1];
1483 for(j=0;j<nhist;j++)
1486 x0=blk->sub[1].lval[2+j];
1490 sprintf(legend, "N(%s(%s=%g) | %s=%g)",
1491 deltag, lambda, foreign_lambda,
1492 lambda, start_lambda);
1496 sprintf(legend, "N(%s | %s=%g)",
1497 dhdl, lambda, start_lambda);
1501 xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv);
1503 for(k=0;k<blk->sub[j+2].nr;k++)
1508 hist=blk->sub[j+2].ival[k];
1511 fprintf(*fp_dhdl,"%g %d\n%g %d\n", xmin, hist,
1515 /* multiple histogram data blocks in one histogram
1516 mean that the second one is the reverse of the first one:
1517 for dhdl derivatives, it's important to know both the
1518 maximum and minimum values */
1524 (*samples) += (int)(sum/nblock_hist);
1530 char **setnames=NULL;
1531 int nnames=nblock_dh;
1533 if (changing_lambda)
1539 snew(setnames, nnames);
1543 if ( changing_lambda && first)
1545 /* lambda is a plotted value */
1546 setnames[j]=gmx_strdup(lambda);
1551 for(i=0;i<fr->nblock;i++)
1553 t_enxblock *blk=&(fr->block[i]);
1554 if (blk->id == enxDH)
1558 /* do the legends */
1560 double foreign_lambda;
1562 derivative=blk->sub[0].ival[0];
1563 foreign_lambda=blk->sub[1].dval[0];
1567 sprintf(buf, "%s %s %g",dhdl,lambda,start_lambda);
1571 sprintf(buf, "%s %s %g",deltag,lambda, foreign_lambda);
1573 setnames[j] = gmx_strdup(buf);
1583 if (len!=blk->sub[2].nr)
1585 gmx_fatal(FARGS, "Length inconsistency in dhdl data");
1594 xvgr_legend(*fp_dhdl, nblock_dh, (const char**)setnames, oenv);
1596 for(i=0;i<nblock_dh;i++)
1606 double time=start_time + delta_time*i;
1608 fprintf(*fp_dhdl,"%.4f", time);
1609 if (fabs(delta_lambda) > 1e-9)
1611 double lambda_now=i*delta_lambda + start_lambda;
1612 fprintf(*fp_dhdl," %.4f", lambda_now);
1614 for(j=0;j<fr->nblock;j++)
1616 t_enxblock *blk=&(fr->block[j]);
1617 if (blk->id == enxDH)
1620 if (blk->sub[2].type == xdr_datatype_float)
1622 value=blk->sub[2].fval[i];
1626 value=blk->sub[2].dval[i];
1628 fprintf(*fp_dhdl," %g", value);
1631 fprintf(*fp_dhdl, "\n");
1637 int gmx_energy(int argc,char *argv[])
1639 const char *desc[] = {
1641 "[TT]g_energy[tt] extracts energy components or distance restraint",
1642 "data from an energy file. The user is prompted to interactively",
1643 "select the desired energy terms.[PAR]",
1645 "Average, RMSD, and drift are calculated with full precision from the",
1646 "simulation (see printed manual). Drift is calculated by performing",
1647 "a least-squares fit of the data to a straight line. The reported total drift",
1648 "is the difference of the fit at the first and last point.",
1649 "An error estimate of the average is given based on a block averages",
1650 "over 5 blocks using the full-precision averages. The error estimate",
1651 "can be performed over multiple block lengths with the options",
1652 "[TT]-nbmin[tt] and [TT]-nbmax[tt].",
1653 "[BB]Note[bb] that in most cases the energy files contains averages over all",
1654 "MD steps, or over many more points than the number of frames in",
1655 "energy file. This makes the [TT]g_energy[tt] statistics output more accurate",
1656 "than the [TT].xvg[tt] output. When exact averages are not present in the energy",
1657 "file, the statistics mentioned above are simply over the single, per-frame",
1658 "energy values.[PAR]",
1660 "The term fluctuation gives the RMSD around the least-squares fit.[PAR]",
1662 "Some fluctuation-dependent properties can be calculated provided",
1663 "the correct energy terms are selected, and that the command line option",
1664 "[TT]-fluct_props[tt] is given. The following properties",
1665 "will be computed:[BR]",
1666 "Property Energy terms needed[BR]",
1667 "---------------------------------------------------[BR]",
1668 "Heat capacity C[SUB]p[sub] (NPT sims): Enthalpy, Temp [BR]",
1669 "Heat capacity C[SUB]v[sub] (NVT sims): Etot, Temp [BR]",
1670 "Thermal expansion coeff. (NPT): Enthalpy, Vol, Temp[BR]",
1671 "Isothermal compressibility: Vol, Temp [BR]",
1672 "Adiabatic bulk modulus: Vol, Temp [BR]",
1673 "---------------------------------------------------[BR]",
1674 "You always need to set the number of molecules [TT]-nmol[tt].",
1675 "The C[SUB]p[sub]/C[SUB]v[sub] computations do [BB]not[bb] include any corrections",
1676 "for quantum effects. Use the [TT]g_dos[tt] program if you need that (and you do).[PAR]"
1677 "When the [TT]-viol[tt] option is set, the time averaged",
1678 "violations are plotted and the running time-averaged and",
1679 "instantaneous sum of violations are recalculated. Additionally",
1680 "running time-averaged and instantaneous distances between",
1681 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
1683 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
1684 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
1685 "The first two options plot the orientation, the last three the",
1686 "deviations of the orientations from the experimental values.",
1687 "The options that end on an 'a' plot the average over time",
1688 "as a function of restraint. The options that end on a 't'",
1689 "prompt the user for restraint label numbers and plot the data",
1690 "as a function of time. Option [TT]-odr[tt] plots the RMS",
1691 "deviation as a function of restraint.",
1692 "When the run used time or ensemble averaged orientation restraints,",
1693 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
1694 "not ensemble-averaged orientations and deviations instead of",
1695 "the time and ensemble averages.[PAR]",
1697 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
1698 "tensor for each orientation restraint experiment. With option",
1699 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
1701 "Option [TT]-odh[tt] extracts and plots the free energy data",
1702 "(Hamiltoian differences and/or the Hamiltonian derivative dhdl)",
1703 "from the [TT]ener.edr[tt] file.[PAR]",
1705 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
1706 "difference with an ideal gas state: [BR]",
1707 " [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]",
1708 " [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]",
1709 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
1710 "the average is over the ensemble (or time in a trajectory).",
1711 "Note that this is in principle",
1712 "only correct when averaging over the whole (Boltzmann) ensemble",
1713 "and using the potential energy. This also allows for an entropy",
1714 "estimate using:[BR]",
1715 " [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]",
1716 " [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",
1719 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
1720 "difference is calculated [BR] dF = -kT [LN][CHEVRON][EXP]-(E[SUB]B[sub]-E[SUB]A[sub])/kT[exp][chevron][SUB]A[sub][ln] ,",
1721 "where E[SUB]A[sub] and E[SUB]B[sub] are the energies from the first and second energy",
1722 "files, and the average is over the ensemble A. The running average",
1723 "of the free energy difference is printed to a file specified by [TT]-ravg[tt].",
1724 "[BB]Note[bb] that the energies must both be calculated from the same trajectory."
1727 static gmx_bool bSum=FALSE,bFee=FALSE,bPrAll=FALSE,bFluct=FALSE,bDriftCorr=FALSE;
1728 static gmx_bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE,bFluctProps=FALSE;
1729 static int skip=0,nmol=1,nbmin=5,nbmax=5;
1730 static real reftemp=300.0,ezero=0;
1732 { "-fee", FALSE, etBOOL, {&bFee},
1733 "Do a free energy estimate" },
1734 { "-fetemp", FALSE, etREAL,{&reftemp},
1735 "Reference temperature for free energy calculation" },
1736 { "-zero", FALSE, etREAL, {&ezero},
1737 "Subtract a zero-point energy" },
1738 { "-sum", FALSE, etBOOL, {&bSum},
1739 "Sum the energy terms selected rather than display them all" },
1740 { "-dp", FALSE, etBOOL, {&bDp},
1741 "Print energies in high precision" },
1742 { "-nbmin", FALSE, etINT, {&nbmin},
1743 "Minimum number of blocks for error estimate" },
1744 { "-nbmax", FALSE, etINT, {&nbmax},
1745 "Maximum number of blocks for error estimate" },
1746 { "-mutot",FALSE, etBOOL, {&bMutot},
1747 "Compute the total dipole moment from the components" },
1748 { "-skip", FALSE, etINT, {&skip},
1749 "Skip number of frames between data points" },
1750 { "-aver", FALSE, etBOOL, {&bPrAll},
1751 "Also print the exact average and rmsd stored in the energy frames (only when 1 term is requested)" },
1752 { "-nmol", FALSE, etINT, {&nmol},
1753 "Number of molecules in your sample: the energies are divided by this number" },
1754 { "-fluct_props", FALSE, etBOOL, {&bFluctProps},
1755 "Compute properties based on energy fluctuations, like heat capacity" },
1756 { "-driftcorr", FALSE, etBOOL, {&bDriftCorr},
1757 "Useful only for calculations of fluctuation properties. The drift in the observables will be subtracted before computing the fluctuation properties."},
1758 { "-fluc", FALSE, etBOOL, {&bFluct},
1759 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
1760 { "-orinst", FALSE, etBOOL, {&bOrinst},
1761 "Analyse instantaneous orientation data" },
1762 { "-ovec", FALSE, etBOOL, {&bOvec},
1763 "Also plot the eigenvectors with [TT]-oten[tt]" }
1765 const char* drleg[] = {
1769 static const char *setnm[] = {
1770 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
1771 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
1772 "Volume", "Pressure"
1775 FILE *out=NULL,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
1781 gmx_localtop_t *top=NULL;
1785 gmx_enxnm_t *enm=NULL;
1786 t_enxframe *frame,*fr=NULL;
1788 #define NEXT (1-cur)
1789 int nre,teller,teller_disre,nfr;
1790 gmx_large_int_t start_step;
1791 int nor=0,nex=0,norfr=0,enx_i=0;
1793 real *bounds=NULL,*violaver=NULL,*oobs=NULL,*orient=NULL,*odrms=NULL;
1794 int *index=NULL,*pair=NULL,norsel=0,*orsel=NULL,*or_label=NULL;
1795 int nbounds=0,npairs;
1796 gmx_bool bDisRe,bDRAll,bORA,bORT,bODA,bODR,bODT,bORIRE,bOTEN,bDHDL;
1797 gmx_bool bFoundStart,bCont,bEDR,bVisco;
1798 double sum,sumaver,sumt,ener,dbl;
1801 int *set=NULL,i,j,k,nset,sss;
1802 gmx_bool *bIsEner=NULL;
1803 char **pairleg,**odtleg,**otenleg;
1806 char *anm_j,*anm_k,*resnm_j,*resnm_k;
1807 int resnr_j,resnr_k;
1808 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
1811 t_enxblock *blk=NULL;
1812 t_enxblock *blk_disre=NULL;
1814 int dh_blocks=0, dh_hists=0, dh_samples=0, dh_lambdas=0;
1817 { efEDR, "-f", NULL, ffREAD },
1818 { efEDR, "-f2", NULL, ffOPTRD },
1819 { efTPX, "-s", NULL, ffOPTRD },
1820 { efXVG, "-o", "energy", ffWRITE },
1821 { efXVG, "-viol", "violaver",ffOPTWR },
1822 { efXVG, "-pairs","pairs", ffOPTWR },
1823 { efXVG, "-ora", "orienta", ffOPTWR },
1824 { efXVG, "-ort", "orientt", ffOPTWR },
1825 { efXVG, "-oda", "orideva", ffOPTWR },
1826 { efXVG, "-odr", "oridevr", ffOPTWR },
1827 { efXVG, "-odt", "oridevt", ffOPTWR },
1828 { efXVG, "-oten", "oriten", ffOPTWR },
1829 { efXVG, "-corr", "enecorr", ffOPTWR },
1830 { efXVG, "-vis", "visco", ffOPTWR },
1831 { efXVG, "-ravg", "runavgdf",ffOPTWR },
1832 { efXVG, "-odh", "dhdl" ,ffOPTWR }
1834 #define NFILE asize(fnm)
1838 CopyRight(stderr,argv[0]);
1840 ppa = add_acf_pargs(&npargs,pa);
1841 parse_common_args(&argc,argv,
1842 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
1843 NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
1845 bDRAll = opt2bSet("-pairs",NFILE,fnm);
1846 bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
1847 bORA = opt2bSet("-ora",NFILE,fnm);
1848 bORT = opt2bSet("-ort",NFILE,fnm);
1849 bODA = opt2bSet("-oda",NFILE,fnm);
1850 bODR = opt2bSet("-odr",NFILE,fnm);
1851 bODT = opt2bSet("-odt",NFILE,fnm);
1852 bORIRE = bORA || bORT || bODA || bODR || bODT;
1853 bOTEN = opt2bSet("-oten",NFILE,fnm);
1854 bDHDL = opt2bSet("-odh",NFILE,fnm);
1859 fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
1860 do_enxnms(fp,&nre,&enm);
1864 bVisco = opt2bSet("-vis",NFILE,fnm);
1866 if (!bDisRe && !bDHDL)
1871 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
1872 for(j=0; j<nset; j++) {
1873 for(i=0; i<nre; i++) {
1874 if (strstr(enm[i].name,setnm[j])) {
1880 if (gmx_strcasecmp(setnm[j],"Volume")==0) {
1881 printf("Enter the box volume (" unit_volume "): ");
1882 if(1 != scanf("%lf",&dbl))
1884 gmx_fatal(FARGS,"Error reading user input");
1888 gmx_fatal(FARGS,"Could not find term %s for viscosity calculation",
1895 set=select_by_name(nre,enm,&nset);
1897 /* Print all the different units once */
1898 sprintf(buf,"(%s)",enm[set[0]].unit);
1899 for(i=1; i<nset; i++) {
1900 for(j=0; j<i; j++) {
1901 if (strcmp(enm[set[i]].unit,enm[set[j]].unit) == 0) {
1907 strcat(buf,enm[set[i]].unit);
1911 out=xvgropen(opt2fn("-o",NFILE,fnm),"Gromacs Energies","Time (ps)",buf,
1915 for(i=0; (i<nset); i++)
1916 leg[i] = enm[set[i]].name;
1918 leg[nset]=strdup("Sum");
1919 xvgr_legend(out,nset+1,(const char**)leg,oenv);
1922 xvgr_legend(out,nset,(const char**)leg,oenv);
1925 for(i=0; (i<nset); i++) {
1927 for (j=0; (j <= F_ETOT); j++)
1928 bIsEner[i] = bIsEner[i] ||
1929 (gmx_strcasecmp(interaction_function[j].longname,leg[i]) == 0);
1932 if (bPrAll && nset > 1) {
1933 gmx_fatal(FARGS,"Printing averages can only be done when a single set is selected");
1938 if (bORIRE || bOTEN)
1939 get_orires_parms(ftp2fn(efTPX,NFILE,fnm),&nor,&nex,&or_label,&oobs);
1952 fprintf(stderr,"Select the orientation restraint labels you want (-1 is all)\n");
1953 fprintf(stderr,"End your selection with 0\n");
1959 if(1 != scanf("%d",&(orsel[j])))
1961 gmx_fatal(FARGS,"Error reading user input");
1963 } while (orsel[j] > 0);
1964 if (orsel[0] == -1) {
1965 fprintf(stderr,"Selecting all %d orientation restraints\n",nor);
1968 for(i=0; i<nor; i++)
1971 /* Build the selection */
1973 for(i=0; i<j; i++) {
1974 for(k=0; k<nor; k++)
1975 if (or_label[k] == orsel[i]) {
1981 fprintf(stderr,"Orientation restraint label %d not found\n",
1985 snew(odtleg,norsel);
1986 for(i=0; i<norsel; i++) {
1987 snew(odtleg[i],256);
1988 sprintf(odtleg[i],"%d",or_label[orsel[i]]);
1991 fort=xvgropen(opt2fn("-ort",NFILE,fnm), "Calculated orientations",
1992 "Time (ps)","",oenv);
1994 fprintf(fort,"%s",orinst_sub);
1995 xvgr_legend(fort,norsel,(const char**)odtleg,oenv);
1998 fodt=xvgropen(opt2fn("-odt",NFILE,fnm),
1999 "Orientation restraint deviation",
2000 "Time (ps)","",oenv);
2002 fprintf(fodt,"%s",orinst_sub);
2003 xvgr_legend(fodt,norsel,(const char**)odtleg,oenv);
2008 foten=xvgropen(opt2fn("-oten",NFILE,fnm),
2009 "Order tensor","Time (ps)","",oenv);
2010 snew(otenleg,bOvec ? nex*12 : nex*3);
2011 for(i=0; i<nex; i++) {
2012 for(j=0; j<3; j++) {
2013 sprintf(buf,"eig%d",j+1);
2014 otenleg[(bOvec ? 12 : 3)*i+j] = strdup(buf);
2017 for(j=0; j<9; j++) {
2018 sprintf(buf,"vec%d%s",j/3+1,j%3==0 ? "x" : (j%3==1 ? "y" : "z"));
2019 otenleg[12*i+3+j] = strdup(buf);
2023 xvgr_legend(foten,bOvec ? nex*12 : nex*3,(const char**)otenleg,oenv);
2028 nbounds=get_bounds(ftp2fn(efTPX,NFILE,fnm),&bounds,&index,&pair,&npairs,
2030 snew(violaver,npairs);
2031 out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
2032 "Time (ps)","nm",oenv);
2033 xvgr_legend(out,2,drleg,oenv);
2035 fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
2036 "Time (ps)","Distance (nm)",oenv);
2037 if (output_env_get_print_xvgr_codes(oenv))
2038 fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
2044 /* Initiate energies and set them to zero */
2053 /* Initiate counters */
2056 bFoundStart = FALSE;
2060 /* This loop searches for the first frame (when -b option is given),
2061 * or when this has been found it reads just one energy frame
2064 bCont = do_enx(fp,&(frame[NEXT]));
2067 timecheck = check_times(frame[NEXT].t);
2069 } while (bCont && (timecheck < 0));
2071 if ((timecheck == 0) && bCont) {
2072 /* We read a valid frame, so we can use it */
2073 fr = &(frame[NEXT]);
2076 /* The frame contains energies, so update cur */
2079 if (edat.nframes % 1000 == 0)
2081 srenew(edat.step,edat.nframes+1000);
2082 memset(&(edat.step[edat.nframes]),0,1000*sizeof(edat.step[0]));
2083 srenew(edat.steps,edat.nframes+1000);
2084 memset(&(edat.steps[edat.nframes]),0,1000*sizeof(edat.steps[0]));
2085 srenew(edat.points,edat.nframes+1000);
2086 memset(&(edat.points[edat.nframes]),0,1000*sizeof(edat.points[0]));
2087 for(i=0; i<nset; i++)
2089 srenew(edat.s[i].ener,edat.nframes+1000);
2090 memset(&(edat.s[i].ener[edat.nframes]),0,
2091 1000*sizeof(edat.s[i].ener[0]));
2093 srenew(edat.s[i].es ,edat.nframes+1000);
2094 memset(&(edat.s[i].es[edat.nframes]),0,
2095 1000*sizeof(edat.s[i].es[0]));
2100 edat.step[nfr] = fr->step;
2105 /* Initiate the previous step data */
2106 start_step = fr->step;
2108 /* Initiate the energy sums */
2109 edat.steps[nfr] = 1;
2110 edat.points[nfr] = 1;
2111 for(i=0; i<nset; i++)
2114 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2115 edat.s[i].es[nfr].sum2 = 0;
2122 edat.steps[nfr] = fr->nsteps;
2124 if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
2128 edat.points[nfr] = 1;
2129 for(i=0; i<nset; i++)
2132 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2133 edat.s[i].es[nfr].sum2 = 0;
2139 edat.points[nfr] = fr->nsum;
2140 for(i=0; i<nset; i++)
2143 edat.s[i].es[nfr].sum = fr->ener[sss].esum;
2144 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
2146 edat.npoints += fr->nsum;
2151 /* The interval does not match fr->nsteps:
2152 * can not do exact averages.
2156 edat.nsteps = fr->step - start_step + 1;
2159 for(i=0; i<nset; i++)
2161 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
2165 * Define distance restraint legends. Can only be done after
2166 * the first frame has been read... (Then we know how many there are)
2168 blk_disre=find_block_id_enxframe(fr, enxDISRE, NULL);
2169 if (bDisRe && bDRAll && !leg && blk_disre)
2174 fa = top->idef.il[F_DISRES].iatoms;
2175 ip = top->idef.iparams;
2176 if (blk_disre->nsub != 2 ||
2177 (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
2179 gmx_incons("Number of disre sub-blocks not equal to 2");
2182 ndisre=blk_disre->sub[0].nr ;
2183 if (ndisre != top->idef.il[F_DISRES].nr/3)
2185 gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
2186 ndisre,top->idef.il[F_DISRES].nr/3);
2188 snew(pairleg,ndisre);
2189 for(i=0; i<ndisre; i++)
2191 snew(pairleg[i],30);
2194 gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
2195 gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
2196 sprintf(pairleg[i],"%d %s %d %s (%d)",
2197 resnr_j,anm_j,resnr_k,anm_k,
2198 ip[fa[3*i]].disres.label);
2200 set=select_it(ndisre,pairleg,&nset);
2202 for(i=0; (i<nset); i++)
2205 sprintf(leg[2*i], "a %s",pairleg[set[i]]);
2206 snew(leg[2*i+1],32);
2207 sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
2209 xvgr_legend(fp_pairs,2*nset,(const char**)leg,oenv);
2213 * Store energies for analysis afterwards...
2215 if (!bDisRe && !bDHDL && (fr->nre > 0)) {
2216 if (edat.nframes % 1000 == 0) {
2217 srenew(time,edat.nframes+1000);
2219 time[edat.nframes] = fr->t;
2223 * Printing time, only when we do not want to skip frames
2225 if (!skip || teller % skip == 0) {
2227 /*******************************************
2228 * D I S T A N C E R E S T R A I N T S
2229 *******************************************/
2233 float *disre_rt = blk_disre->sub[0].fval;
2234 float *disre_rm3tav = blk_disre->sub[1].fval;
2236 double *disre_rt = blk_disre->sub[0].dval;
2237 double *disre_rm3tav = blk_disre->sub[1].dval;
2240 print_time(out,fr->t);
2241 if (violaver == NULL)
2242 snew(violaver,ndisre);
2244 /* Subtract bounds from distances, to calculate violations */
2245 calc_violations(disre_rt, disre_rm3tav,
2246 nbounds,pair,bounds,violaver,&sumt,&sumaver);
2248 fprintf(out," %8.4f %8.4f\n",sumaver,sumt);
2250 print_time(fp_pairs,fr->t);
2251 for(i=0; (i<nset); i++) {
2253 fprintf(fp_pairs," %8.4f", mypow(disre_rm3tav[sss],minthird));
2254 fprintf(fp_pairs," %8.4f", disre_rt[sss]);
2256 fprintf(fp_pairs,"\n");
2263 do_dhdl(fr, &fp_dhdl, opt2fn("-odh",NFILE,fnm),
2264 &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas,
2267 /*******************************************
2269 *******************************************/
2274 /* We skip frames with single points (usually only the first frame),
2275 * since they would result in an average plot with outliers.
2278 print_time(out,fr->t);
2279 print1(out,bDp,fr->ener[set[0]].e);
2280 print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
2281 print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
2287 print_time(out,fr->t);
2291 for(i=0; i<nset; i++)
2293 sum += fr->ener[set[i]].e;
2295 print1(out,bDp,sum/nmol-ezero);
2299 for(i=0; (i<nset); i++)
2303 print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
2307 print1(out,bDp,fr->ener[set[i]].e);
2315 /* we first count the blocks that have id 0: the orire blocks */
2317 for(b=0;b<fr->nblock;b++)
2319 if (fr->block[b].id == mde_block_type_orire)
2323 blk = find_block_id_enxframe(fr, enx_i, NULL);
2327 xdr_datatype dt=xdr_datatype_float;
2329 xdr_datatype dt=xdr_datatype_double;
2333 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2335 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2338 vals=blk->sub[0].fval;
2340 vals=blk->sub[0].dval;
2343 if (blk->sub[0].nr != (size_t)nor)
2344 gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)", blk->sub[0].nr);
2347 for(i=0; i<nor; i++)
2348 orient[i] += vals[i];
2352 for(i=0; i<nor; i++)
2353 odrms[i] += sqr(vals[i]-oobs[i]);
2357 fprintf(fort," %10f",fr->t);
2358 for(i=0; i<norsel; i++)
2359 fprintf(fort," %g",vals[orsel[i]]);
2364 fprintf(fodt," %10f",fr->t);
2365 for(i=0; i<norsel; i++)
2366 fprintf(fodt," %g", vals[orsel[i]]-oobs[orsel[i]]);
2371 blk = find_block_id_enxframe(fr, enxORT, NULL);
2375 xdr_datatype dt=xdr_datatype_float;
2377 xdr_datatype dt=xdr_datatype_double;
2381 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2382 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2384 vals=blk->sub[0].fval;
2386 vals=blk->sub[0].dval;
2389 if (blk->sub[0].nr != (size_t)(nex*12))
2390 gmx_fatal(FARGS,"Number of orientation experiments in energy file (%g) does not match with the topology (%d)",
2391 blk->sub[0].nr/12, nex);
2392 fprintf(foten," %10f",fr->t);
2393 for(i=0; i<nex; i++)
2394 for(j=0; j<(bOvec?12:3); j++)
2395 fprintf(foten," %g",vals[i*12+j]);
2396 fprintf(foten,"\n");
2402 } while (bCont && (timecheck == 0));
2404 fprintf(stderr,"\n");
2418 out = xvgropen(opt2fn("-ora",NFILE,fnm),
2419 "Average calculated orientations",
2420 "Restraint label","",oenv);
2422 fprintf(out,"%s",orinst_sub);
2423 for(i=0; i<nor; i++)
2424 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr);
2428 out = xvgropen(opt2fn("-oda",NFILE,fnm),
2429 "Average restraint deviation",
2430 "Restraint label","",oenv);
2432 fprintf(out,"%s",orinst_sub);
2433 for(i=0; i<nor; i++)
2434 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr-oobs[i]);
2438 out = xvgropen(opt2fn("-odr",NFILE,fnm),
2439 "RMS orientation restraint deviations",
2440 "Restraint label","",oenv);
2442 fprintf(out,"%s",orinst_sub);
2443 for(i=0; i<nor; i++)
2444 fprintf(out,"%5d %g\n",or_label[i],sqrt(odrms[i]/norfr));
2452 analyse_disre(opt2fn("-viol",NFILE,fnm),
2453 teller_disre,violaver,bounds,index,pair,nbounds,oenv);
2460 printf("\n\nWrote %d lambda values with %d samples as ",
2461 dh_lambdas, dh_samples);
2464 printf("%d dH histograms ", dh_hists);
2468 printf("%d dH data blocks ", dh_blocks);
2470 printf("to %s\n", opt2fn("-odh",NFILE,fnm));
2475 gmx_fatal(FARGS, "No dH data in %s\n", opt2fn("-f",NFILE,fnm));
2481 double dt = (frame[cur].t-start_t)/(edat.nframes-1);
2482 analyse_ener(opt2bSet("-corr",NFILE,fnm),opt2fn("-corr",NFILE,fnm),
2483 bFee,bSum,bFluct,opt2parg_bSet("-nmol",npargs,ppa),
2484 bVisco,opt2fn("-vis",NFILE,fnm),
2486 start_step,start_t,frame[cur].step,frame[cur].t,
2488 nset,set,bIsEner,leg,enm,Vaver,ezero,nbmin,nbmax,
2491 calc_fluctuation_props(stdout,bDriftCorr,dt,nset,set,nmol,leg,&edat,
2494 if (opt2bSet("-f2",NFILE,fnm)) {
2495 fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
2496 reftemp, nset, set, leg, &edat, time ,oenv);
2500 const char *nxy = "-nxy";
2502 do_view(oenv,opt2fn("-o",NFILE,fnm),nxy);
2503 do_view(oenv,opt2fn_null("-ravg",NFILE,fnm),nxy);
2504 do_view(oenv,opt2fn_null("-ora",NFILE,fnm),nxy);
2505 do_view(oenv,opt2fn_null("-ort",NFILE,fnm),nxy);
2506 do_view(oenv,opt2fn_null("-oda",NFILE,fnm),nxy);
2507 do_view(oenv,opt2fn_null("-odr",NFILE,fnm),nxy);
2508 do_view(oenv,opt2fn_null("-odt",NFILE,fnm),nxy);
2509 do_view(oenv,opt2fn_null("-oten",NFILE,fnm),nxy);
2510 do_view(oenv,opt2fn_null("-odh",NFILE,fnm),nxy);