1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * Green Red Orange Magenta Azure Cyan Skyblue
45 #include "gmx_fatal.h"
59 #include "mtop_util.h"
63 static real minthird=-1.0/3.0,minsixth=-1.0/6.0;
81 gmx_large_int_t nsteps;
82 gmx_large_int_t npoints;
90 static double mypow(double x,double y)
98 static int *select_it(int nre,char *nm[],int *nset)
103 gmx_bool bVerbose = TRUE;
105 if ((getenv("VERBOSE")) != NULL)
108 fprintf(stderr,"Select the terms you want from the following list\n");
109 fprintf(stderr,"End your selection with 0\n");
112 for(k=0; (k<nre); ) {
113 for(j=0; (j<4) && (k<nre); j++,k++)
114 fprintf(stderr," %3d=%14s",k+1,nm[k]);
115 fprintf(stderr,"\n");
121 if(1 != scanf("%d",&n))
123 gmx_fatal(FARGS,"Error reading user input");
125 if ((n>0) && (n<=nre))
130 for(i=(*nset)=0; (i<nre); i++)
139 static void chomp(char *buf)
141 int len = strlen(buf);
143 while ((len > 0) && (buf[len-1] == '\n')) {
149 static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
152 int n,k,kk,j,i,nmatch,nind,nss;
154 gmx_bool bEOF,bVerbose = TRUE,bLong=FALSE;
155 char *ptr,buf[STRLEN];
156 const char *fm4="%3d %-14s";
157 const char *fm2="%3d %-34s";
160 if ((getenv("VERBOSE")) != NULL)
163 fprintf(stderr,"\n");
164 fprintf(stderr,"Select the terms you want from the following list by\n");
165 fprintf(stderr,"selecting either (part of) the name or the number or a combination.\n");
166 fprintf(stderr,"End your selection with an empty line or a zero.\n");
167 fprintf(stderr,"-------------------------------------------------------------------\n");
171 for(k=0; k<nre; k++) {
172 newnm[k] = strdup(nm[k].name);
173 /* Insert dashes in all the names */
174 while ((ptr = strchr(newnm[k],' ')) != NULL) {
180 fprintf(stderr,"\n");
183 for(kk=k; kk<k+4; kk++) {
184 if (kk < nre && strlen(nm[kk].name) > 14) {
192 fprintf(stderr,fm4,k+1,newnm[k]);
198 fprintf(stderr,fm2,k+1,newnm[k]);
207 fprintf(stderr,"\n\n");
213 while (!bEOF && (fgets2(buf,STRLEN-1,stdin))) {
214 /* Remove newlines */
220 /* Empty line means end of input */
221 bEOF = (strlen(buf) == 0);
226 /* First try to read an integer */
227 nss = sscanf(ptr,"%d",&nind);
229 /* Zero means end of input */
232 } else if ((1<=nind) && (nind<=nre)) {
235 fprintf(stderr,"number %d is out of range\n",nind);
239 /* Now try to read a string */
242 for(nind=0; nind<nre; nind++) {
243 if (gmx_strcasecmp(newnm[nind],ptr) == 0) {
251 for(nind=0; nind<nre; nind++) {
252 if (gmx_strncasecmp(newnm[nind],ptr,i) == 0) {
258 fprintf(stderr,"String '%s' does not match anything\n",ptr);
263 /* Look for the first space, and remove spaces from there */
264 if ((ptr = strchr(ptr,' ')) != NULL) {
267 } while (!bEOF && (ptr && (strlen(ptr) > 0)));
272 for(i=(*nset)=0; (i<nre); i++)
279 gmx_fatal(FARGS,"No energy terms selected");
281 for(i=0; (i<nre); i++)
288 static void get_dhdl_parms(const char *topnm, t_inputrec *ir)
295 /* all we need is the ir to be able to write the label */
296 read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,&mtop);
299 static void get_orires_parms(const char *topnm,
300 int *nor,int *nex,int **label,real **obs)
311 read_tpx(topnm,&ir,box,&natoms,NULL,NULL,NULL,&mtop);
312 top = gmx_mtop_generate_local_top(&mtop,&ir);
314 ip = top->idef.iparams;
315 iatom = top->idef.il[F_ORIRES].iatoms;
317 /* Count how many distance restraint there are... */
318 nb = top->idef.il[F_ORIRES].nr;
320 gmx_fatal(FARGS,"No orientation restraints in topology!\n");
326 for(i=0; i<nb; i+=3) {
327 (*label)[i/3] = ip[iatom[i]].orires.label;
328 (*obs)[i/3] = ip[iatom[i]].orires.obs;
329 if (ip[iatom[i]].orires.ex >= *nex)
330 *nex = ip[iatom[i]].orires.ex+1;
332 fprintf(stderr,"Found %d orientation restraints with %d experiments",
336 static int get_bounds(const char *topnm,
337 real **bounds,int **index,int **dr_pair,int *npairs,
338 gmx_mtop_t *mtop,gmx_localtop_t **ltop,t_inputrec *ir)
341 t_functype *functype;
343 int natoms,i,j,k,type,ftype,natom;
351 read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,mtop);
353 top = gmx_mtop_generate_local_top(mtop,ir);
356 functype = top->idef.functype;
357 ip = top->idef.iparams;
359 /* Count how many distance restraint there are... */
360 nb=top->idef.il[F_DISRES].nr;
362 gmx_fatal(FARGS,"No distance restraints in topology!\n");
364 /* Allocate memory */
369 /* Fill the bound array */
371 for(i=0; (i<top->idef.ntypes); i++) {
373 if (ftype == F_DISRES) {
375 label1 = ip[i].disres.label;
376 b[nb] = ip[i].disres.up1;
383 /* Fill the index array */
385 disres = &(top->idef.il[F_DISRES]);
386 iatom = disres->iatoms;
387 for(i=j=k=0; (i<disres->nr); ) {
389 ftype = top->idef.functype[type];
390 natom = interaction_function[ftype].nratoms+1;
391 if (label1 != top->idef.iparams[type].disres.label) {
393 label1 = top->idef.iparams[type].disres.label;
402 gmx_incons("get_bounds for distance restraints");
410 static void calc_violations(real rt[],real rav3[],int nb,int index[],
411 real bounds[],real *viol,double *st,double *sa)
413 const real sixth=1.0/6.0;
415 double rsum,rav,sumaver,sumt;
419 for(i=0; (i<nb); i++) {
422 for(j=index[i]; (j<index[i+1]); j++) {
424 viol[j] += mypow(rt[j],-3.0);
426 rsum += mypow(rt[j],-6);
428 rsum = max(0.0,mypow(rsum,-sixth)-bounds[i]);
429 rav = max(0.0,mypow(rav, -sixth)-bounds[i]);
438 static void analyse_disre(const char *voutfn, int nframes,
439 real violaver[], real bounds[], int index[],
440 int pair[], int nbounds,
441 const output_env_t oenv)
444 double sum,sumt,sumaver;
447 /* Subtract bounds from distances, to calculate violations */
448 calc_violations(violaver,violaver,
449 nbounds,pair,bounds,NULL,&sumt,&sumaver);
452 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
454 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",
457 vout=xvgropen(voutfn,"r\\S-3\\N average violations","DR Index","nm",
461 for(i=0; (i<nbounds); i++) {
462 /* Do ensemble averaging */
464 for(j=pair[i]; (j<pair[i+1]); j++)
465 sumaver += sqr(violaver[j]/nframes);
466 sumaver = max(0.0,mypow(sumaver,minsixth)-bounds[i]);
469 sum = max(sum,sumaver);
470 fprintf(vout,"%10d %10.5e\n",index[i],sumaver);
473 for(j=0; (j<dr.ndr); j++)
474 fprintf(vout,"%10d %10.5e\n",j,mypow(violaver[j]/nframes,minthird));
478 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
480 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",sum);
482 do_view(oenv,voutfn,"-graphtype bar");
485 static void einstein_visco(const char *fn,const char *fni,int nsets,
486 int nframes,real **sum,
487 real V,real T,int nsteps,double time[],
488 const output_env_t oenv)
491 double av[4],avold[4];
498 dt = (time[1]-time[0]);
501 for(i=0; i<=nsets; i++)
503 fp0=xvgropen(fni,"Shear viscosity integral",
504 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N ps)",oenv);
505 fp1=xvgropen(fn,"Shear viscosity using Einstein relation",
506 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N)",oenv);
507 for(i=1; i<nf4; i++) {
508 fac = dt*nframes/nsteps;
509 for(m=0; m<=nsets; m++)
511 for(j=0; j<nframes-i; j++) {
512 for(m=0; m<nsets; m++) {
513 di = sqr(fac*(sum[m][j+i]-sum[m][j]));
516 av[nsets] += di/nsets;
519 /* Convert to SI for the viscosity */
520 fac = (V*NANO*NANO*NANO*PICO*1e10)/(2*BOLTZMANN*T)/(nframes-i);
521 fprintf(fp0,"%10g",time[i]-time[0]);
522 for(m=0; (m<=nsets); m++) {
524 fprintf(fp0," %10g",av[m]);
527 fprintf(fp1,"%10g",0.5*(time[i]+time[i-1])-time[0]);
528 for(m=0; (m<=nsets); m++) {
529 fprintf(fp1," %10g",(av[m]-avold[m])/dt);
549 gmx_large_int_t nst_min;
552 static void clear_ee_sum(ee_sum_t *ees)
560 static void add_ee_sum(ee_sum_t *ees,double sum,int np)
566 static void add_ee_av(ee_sum_t *ees)
570 av = ees->sum/ees->np;
577 static double calc_ee2(int nb,ee_sum_t *ees)
579 return (ees->sav2/nb - dsqr(ees->sav/nb))/(nb - 1);
582 static void set_ee_av(ener_ee_t *eee)
586 char buf[STEPSTRSIZE];
587 fprintf(debug,"Storing average for err.est.: %s steps\n",
588 gmx_step_str(eee->nst,buf));
590 add_ee_av(&eee->sum);
592 if (eee->b == 1 || eee->nst < eee->nst_min)
594 eee->nst_min = eee->nst;
599 static void calc_averages(int nset,enerdata_t *edat,int nbmin,int nbmax)
602 double sum,sum2,sump,see2;
603 gmx_large_int_t steps,np,p,bound_nb;
607 double x,sx,sy,sxx,sxy;
610 /* Check if we have exact statistics over all points */
611 for(i=0; i<nset; i++)
614 ed->bExactStat = FALSE;
615 if (edat->npoints > 0)
617 /* All energy file sum entries 0 signals no exact sums.
618 * But if all energy values are 0, we still have exact sums.
621 for(f=0; f<edat->nframes && !ed->bExactStat; f++)
623 if (ed->ener[i] != 0)
627 ed->bExactStat = (ed->es[f].sum != 0);
631 ed->bExactStat = TRUE;
637 for(i=0; i<nset; i++)
648 for(nb=nbmin; nb<=nbmax; nb++)
651 clear_ee_sum(&eee[nb].sum);
655 for(f=0; f<edat->nframes; f++)
661 /* Add the sum and the sum of variances to the totals. */
667 sum2 += dsqr(sum/np - (sum + es->sum)/(np + p))
673 /* Add a single value to the sum and sum of squares. */
679 /* sum has to be increased after sum2 */
683 /* For the linear regression use variance 1/p.
684 * Note that sump is the sum, not the average, so we don't need p*.
686 x = edat->step[f] - 0.5*(edat->steps[f] - 1);
692 for(nb=nbmin; nb<=nbmax; nb++)
694 /* Check if the current end step is closer to the desired
695 * block boundary than the next end step.
697 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
698 if (eee[nb].nst > 0 &&
699 bound_nb - edat->step[f-1]*nb < edat->step[f]*nb - bound_nb)
709 eee[nb].nst += edat->step[f] - edat->step[f-1];
713 add_ee_sum(&eee[nb].sum,es->sum,edat->points[f]);
717 add_ee_sum(&eee[nb].sum,edat->s[i].ener[f],1);
719 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
720 if (edat->step[f]*nb >= bound_nb)
727 edat->s[i].av = sum/np;
730 edat->s[i].rmsd = sqrt(sum2/np);
734 edat->s[i].rmsd = sqrt(sum2/np - dsqr(edat->s[i].av));
737 if (edat->nframes > 1)
739 edat->s[i].slope = (np*sxy - sx*sy)/(np*sxx - sx*sx);
743 edat->s[i].slope = 0;
748 for(nb=nbmin; nb<=nbmax; nb++)
750 /* Check if we actually got nb blocks and if the smallest
751 * block is not shorter than 80% of the average.
755 char buf1[STEPSTRSIZE],buf2[STEPSTRSIZE];
756 fprintf(debug,"Requested %d blocks, we have %d blocks, min %s nsteps %s\n",
758 gmx_step_str(eee[nb].nst_min,buf1),
759 gmx_step_str(edat->nsteps,buf2));
761 if (eee[nb].b == nb && 5*nb*eee[nb].nst_min >= 4*edat->nsteps)
763 see2 += calc_ee2(nb,&eee[nb].sum);
769 edat->s[i].ee = sqrt(see2/nee);
779 static enerdata_t *calc_sum(int nset,enerdata_t *edat,int nbmin,int nbmax)
790 snew(s->ener,esum->nframes);
791 snew(s->es ,esum->nframes);
793 s->bExactStat = TRUE;
795 for(i=0; i<nset; i++)
797 if (!edat->s[i].bExactStat)
799 s->bExactStat = FALSE;
801 s->slope += edat->s[i].slope;
804 for(f=0; f<edat->nframes; f++)
807 for(i=0; i<nset; i++)
809 sum += edat->s[i].ener[f];
813 for(i=0; i<nset; i++)
815 sum += edat->s[i].es[f].sum;
821 calc_averages(1,esum,nbmin,nbmax);
826 static char *ee_pr(double ee,char *buf)
833 sprintf(buf,"%s","--");
837 /* Round to two decimals by printing. */
838 sprintf(tmp,"%.1e",ee);
839 sscanf(tmp,"%lf",&rnd);
840 sprintf(buf,"%g",rnd);
846 static void remove_drift(int nset,int nbmin,int nbmax,real dt,enerdata_t *edat)
848 /* Remove the drift by performing a fit to y = ax+b.
849 Uses 5 iterations. */
851 double delta,d,sd,sd2;
853 edat->npoints = edat->nframes;
854 edat->nsteps = edat->nframes;
858 for(i=0; (i<nset); i++)
860 delta = edat->s[i].slope*dt;
863 fprintf(debug,"slope for set %d is %g\n",i,edat->s[i].slope);
865 for(j=0; (j<edat->nframes); j++)
867 edat->s[i].ener[j] -= j*delta;
868 edat->s[i].es[j].sum = 0;
869 edat->s[i].es[j].sum2 = 0;
872 calc_averages(nset,edat,nbmin,nbmax);
876 static void calc_fluctuation_props(FILE *fp,
877 gmx_bool bDriftCorr,real dt,
878 int nset,int set[],int nmol,
879 char **leg,enerdata_t *edat,
883 double vvhh,vv,v,h,hh2,vv2,varv,hh,varh,tt,cv,cp,alpha,kappa,dcp,et,varet;
885 enum { eVol, eEnth, eTemp, eEtot, eNR };
886 const char *my_ener[] = { "Volume", "Enthalpy", "Temperature", "Total Energy" };
889 NANO3 = NANO*NANO*NANO;
892 fprintf(fp,"\nYou may want to use the -driftcorr flag in order to correct\n"
893 "for spurious drift in the graphs. Note that this is not\n"
894 "a substitute for proper equilibration and sampling!\n");
898 remove_drift(nset,nbmin,nbmax,dt,edat);
900 for(i=0; (i<eNR); i++)
902 for(ii[i]=0; (ii[i]<nset &&
903 (gmx_strcasecmp(leg[ii[i]],my_ener[i]) != 0)); ii[i]++)
906 fprintf(fp,"Found %s data.\n",my_ener[i]);
908 /* Compute it all! */
909 vvhh = alpha = kappa = cp = dcp = cv = NOTSET;
913 if (ii[eTemp] < nset)
915 tt = edat->s[ii[eTemp]].av;
919 if ((ii[eVol] < nset) && (ii[eTemp] < nset))
921 vv = edat->s[ii[eVol]].av*NANO3;
922 varv = dsqr(edat->s[ii[eVol]].rmsd*NANO3);
923 kappa = (varv/vv)/(BOLTZMANN*tt);
927 if ((ii[eEnth] < nset) && (ii[eTemp] < nset))
929 hh = KILO*edat->s[ii[eEnth]].av/AVOGADRO;
930 varh = dsqr(KILO*edat->s[ii[eEnth]].rmsd/AVOGADRO);
931 cp = AVOGADRO*((varh/nmol)/(BOLTZMANN*tt*tt));
935 if ((ii[eEtot] < nset) && (hh == NOTSET) && (tt != NOTSET))
937 /* Only compute cv in constant volume runs, which we can test
938 by checking whether the enthalpy was computed.
940 et = edat->s[ii[eEtot]].av;
941 varet = sqr(edat->s[ii[eEtot]].rmsd);
942 cv = KILO*((varet/nmol)/(BOLTZ*tt*tt));
945 if ((ii[eVol] < nset) && (ii[eEnth] < nset) && (ii[eTemp] < nset))
948 for(j=0; (j<edat->nframes); j++)
950 v = edat->s[ii[eVol]].ener[j]*NANO3;
951 h = KILO*edat->s[ii[eEnth]].ener[j]/AVOGADRO;
954 vvhh /= edat->nframes;
955 alpha = (vvhh-vv*hh)/(vv*BOLTZMANN*tt*tt);
956 dcp = (vv*AVOGADRO/nmol)*tt*sqr(alpha)/(kappa);
962 fprintf(fp,"\nWARNING: nmol = %d, this may not be what you want.\n",
964 fprintf(fp,"\nTemperature dependent fluctuation properties at T = %g.\n",tt);
965 fprintf(fp,"\nHeat capacities obtained from fluctuations do *not* include\n");
966 fprintf(fp,"quantum corrections. If you want to get a more accurate estimate\n");
967 fprintf(fp,"please use the g_dos program.\n\n");
968 fprintf(fp,"WARNING: Please verify that your simulations are converged and perform\n"
969 "a block-averaging error analysis (not implemented in g_energy yet)\n");
974 fprintf(fp,"varv = %10g (m^6)\n",varv*AVOGADRO/nmol);
976 fprintf(fp,"vvhh = %10g (m^3 J)\n",vvhh);
979 fprintf(fp,"Volume = %10g m^3/mol\n",
982 fprintf(fp,"Enthalpy = %10g kJ/mol\n",
983 hh*AVOGADRO/(KILO*nmol));
985 fprintf(fp,"Coefficient of Thermal Expansion Alpha_P = %10g (1/K)\n",
989 fprintf(fp,"Isothermal Compressibility Kappa = %10g (J/m^3)\n",
991 fprintf(fp,"Adiabatic bulk modulus = %10g (m^3/J)\n",
995 fprintf(fp,"Heat capacity at constant pressure Cp = %10g J/mol K\n",
998 fprintf(fp,"Heat capacity at constant volume Cv = %10g J/mol K\n",
1001 fprintf(fp,"Cp-Cv = %10g J/mol K\n",
1003 please_cite(fp,"Allen1987a");
1007 fprintf(fp,"You should select the temperature in order to obtain fluctuation properties.\n");
1011 static void analyse_ener(gmx_bool bCorr,const char *corrfn,
1012 gmx_bool bFee,gmx_bool bSum,gmx_bool bFluct,gmx_bool bTempFluct,
1013 gmx_bool bVisco,const char *visfn,int nmol,
1014 gmx_large_int_t start_step,double start_t,
1015 gmx_large_int_t step,double t,
1016 double time[], real reftemp,
1018 int nset,int set[],gmx_bool *bIsEner,
1019 char **leg,gmx_enxnm_t *enm,
1020 real Vaver,real ezero,
1021 int nbmin,int nbmax,
1022 const output_env_t oenv)
1025 /* Check out the printed manual for equations! */
1026 double Dt,aver,stddev,errest,delta_t,totaldrift;
1027 enerdata_t *esum=NULL;
1028 real xxx,integral,intBulk,Temp=0,Pres=0;
1029 real sfrac,oldfrac,diffsum,diffav,fstep,pr_aver,pr_stddev,pr_errest;
1030 double beta=0,expE,expEtot,*fee=NULL;
1031 gmx_large_int_t nsteps;
1032 int nexact,nnotexact;
1036 char buf[256],eebuf[100];
1038 nsteps = step - start_step + 1;
1040 fprintf(stdout,"Not enough steps (%s) for statistics\n",
1041 gmx_step_str(nsteps,buf));
1044 /* Calculate the time difference */
1045 delta_t = t - start_t;
1047 fprintf(stdout,"\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
1048 gmx_step_str(nsteps,buf),start_t,t,nset);
1050 calc_averages(nset,edat,nbmin,nbmax);
1053 esum = calc_sum(nset,edat,nbmin,nbmax);
1056 if (edat->npoints == 0) {
1062 for(i=0; (i<nset); i++) {
1063 if (edat->s[i].bExactStat) {
1071 if (nnotexact == 0) {
1072 fprintf(stdout,"All statistics are over %s points\n",
1073 gmx_step_str(edat->npoints,buf));
1074 } else if (nexact == 0 || edat->npoints == edat->nframes) {
1075 fprintf(stdout,"All statistics are over %d points (frames)\n",
1078 fprintf(stdout,"The term%s",nnotexact==1 ? "" : "s");
1079 for(i=0; (i<nset); i++) {
1080 if (!edat->s[i].bExactStat) {
1081 fprintf(stdout," '%s'",leg[i]);
1084 fprintf(stdout," %s has statistics over %d points (frames)\n",
1085 nnotexact==1 ? "is" : "are",edat->nframes);
1086 fprintf(stdout,"All other statistics are over %s points\n",
1087 gmx_step_str(edat->npoints,buf));
1089 fprintf(stdout,"\n");
1091 fprintf(stdout,"%-24s %10s %10s %10s %10s",
1092 "Energy","Average","Err.Est.","RMSD","Tot-Drift");
1094 fprintf(stdout," %10s\n","-kT ln<e^(E/kT)>");
1096 fprintf(stdout,"\n");
1097 fprintf(stdout,"-------------------------------------------------------------------------------\n");
1099 /* Initiate locals, only used with -sum */
1102 beta = 1.0/(BOLTZ*reftemp);
1105 for(i=0; (i<nset); i++) {
1106 aver = edat->s[i].av;
1107 stddev = edat->s[i].rmsd;
1108 errest = edat->s[i].ee;
1112 for(j=0; (j<edat->nframes); j++) {
1113 expE += exp(beta*(edat->s[i].ener[j] - aver)/nmol);
1116 expEtot+=expE/edat->nframes;
1118 fee[i] = log(expE/edat->nframes)/beta + aver/nmol;
1120 if (strstr(leg[i],"empera") != NULL) {
1122 } else if (strstr(leg[i],"olum") != NULL) {
1124 } else if (strstr(leg[i],"essure") != NULL) {
1128 pr_aver = aver/nmol-ezero;
1129 pr_stddev = stddev/nmol;
1130 pr_errest = errest/nmol;
1138 /* Multiply the slope in steps with the number of steps taken */
1139 totaldrift = (edat->nsteps - 1)*edat->s[i].slope;
1145 fprintf(stdout,"%-24s %10g %10s %10g %10g",
1146 leg[i],pr_aver,ee_pr(pr_errest,eebuf),pr_stddev,totaldrift);
1148 fprintf(stdout," %10g",fee[i]);
1150 fprintf(stdout," (%s)\n",enm[set[i]].unit);
1153 for(j=0; (j<edat->nframes); j++)
1154 edat->s[i].ener[j] -= aver;
1158 totaldrift = (edat->nsteps - 1)*esum->s[0].slope;
1159 fprintf(stdout,"%-24s %10g %10s %10s %10g (%s)",
1160 "Total",esum->s[0].av/nmol,ee_pr(esum->s[0].ee/nmol,eebuf),
1161 "--",totaldrift/nmol,enm[set[0]].unit);
1162 /* pr_aver,pr_stddev,a,totaldrift */
1164 fprintf(stdout," %10g %10g\n",
1165 log(expEtot)/beta + esum->s[0].av/nmol,log(expEtot)/beta);
1167 fprintf(stdout,"\n");
1170 /* Do correlation function */
1171 if (edat->nframes > 1)
1173 Dt = delta_t/(edat->nframes - 1);
1180 const char* leg[] = { "Shear", "Bulk" };
1185 /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
1187 /* Symmetrise tensor! (and store in first three elements)
1188 * And subtract average pressure!
1191 for(i=0; i<12; i++) {
1192 snew(eneset[i],edat->nframes);
1195 for(i=0; i<3; i++) {
1196 snew(enesum[i],edat->nframes);
1198 for(i=0; (i<edat->nframes); i++) {
1199 eneset[0][i] = 0.5*(edat->s[1].ener[i]+edat->s[3].ener[i]);
1200 eneset[1][i] = 0.5*(edat->s[2].ener[i]+edat->s[6].ener[i]);
1201 eneset[2][i] = 0.5*(edat->s[5].ener[i]+edat->s[7].ener[i]);
1202 for(j=3; j<=11; j++) {
1203 eneset[j][i] = edat->s[j].ener[i];
1205 eneset[11][i] -= Pres;
1206 enesum[0][i] = 0.5*(edat->s[1].es[i].sum+edat->s[3].es[i].sum);
1207 enesum[1][i] = 0.5*(edat->s[2].es[i].sum+edat->s[6].es[i].sum);
1208 enesum[2][i] = 0.5*(edat->s[5].es[i].sum+edat->s[7].es[i].sum);
1211 einstein_visco("evisco.xvg","eviscoi.xvg",
1212 3,edat->nframes,enesum,Vaver,Temp,nsteps,time,oenv);
1214 /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
1215 /* Do it for shear viscosity */
1216 strcpy(buf,"Shear Viscosity");
1217 low_do_autocorr(corrfn,oenv,buf,edat->nframes,3,
1218 (edat->nframes+1)/2,eneset,Dt,
1219 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1221 /* Now for bulk viscosity */
1222 strcpy(buf,"Bulk Viscosity");
1223 low_do_autocorr(corrfn,oenv,buf,edat->nframes,1,
1224 (edat->nframes+1)/2,&(eneset[11]),Dt,
1225 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1227 factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
1228 fp=xvgropen(visfn,buf,"Time (ps)","\\8h\\4 (cp)",oenv);
1229 xvgr_legend(fp,asize(leg),leg,oenv);
1231 /* Use trapezium rule for integration */
1234 nout = get_acfnout();
1235 if ((nout < 2) || (nout >= edat->nframes/2))
1236 nout = edat->nframes/2;
1237 for(i=1; (i<nout); i++)
1239 integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
1240 intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
1241 fprintf(fp,"%10g %10g %10g\n",(i*Dt),integral,intBulk);
1247 strcpy(buf,"Autocorrelation of Energy Fluctuations");
1249 strcpy(buf,"Energy Autocorrelation");
1251 do_autocorr(corrfn,oenv,buf,edat->nframes,
1253 bSum ? &edat->s[nset-1].ener : eneset,
1254 (delta_t/edat->nframes),eacNormal,FALSE);
1260 static void print_time(FILE *fp,double t)
1262 fprintf(fp,"%12.6f",t);
1265 static void print1(FILE *fp,gmx_bool bDp,real e)
1268 fprintf(fp," %16.12f",e);
1270 fprintf(fp," %10.6f",e);
1273 static void fec(const char *ene2fn, const char *runavgfn,
1274 real reftemp, int nset, int set[], char *leg[],
1275 enerdata_t *edat, double time[],
1276 const output_env_t oenv)
1278 const char* ravgleg[] = { "\\8D\\4E = E\\sB\\N-E\\sA\\N",
1279 "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N" };
1282 int nre,timecheck,step,nenergy,nenergy2,maxenergy;
1288 gmx_enxnm_t *enm=NULL;
1292 /* read second energy file */
1295 enx = open_enx(ene2fn,"r");
1296 do_enxnms(enx,&(fr->nre),&enm);
1298 snew(eneset2,nset+1);
1303 /* This loop searches for the first frame (when -b option is given),
1304 * or when this has been found it reads just one energy frame
1307 bCont = do_enx(enx,fr);
1310 timecheck = check_times(fr->t);
1312 } while (bCont && (timecheck < 0));
1314 /* Store energies for analysis afterwards... */
1315 if ((timecheck == 0) && bCont) {
1317 if ( nenergy2 >= maxenergy ) {
1319 for(i=0; i<=nset; i++)
1320 srenew(eneset2[i],maxenergy);
1322 if (fr->t != time[nenergy2])
1323 fprintf(stderr,"\nWARNING time mismatch %g!=%g at frame %s\n",
1324 fr->t, time[nenergy2], gmx_step_str(fr->step,buf));
1325 for(i=0; i<nset; i++)
1326 eneset2[i][nenergy2] = fr->ener[set[i]].e;
1330 } while (bCont && (timecheck == 0));
1333 if (edat->nframes != nenergy2) {
1334 fprintf(stderr,"\nWARNING file length mismatch %d!=%d\n",
1335 edat->nframes,nenergy2);
1337 nenergy = min(edat->nframes,nenergy2);
1339 /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
1342 fp=xvgropen(runavgfn,"Running average free energy difference",
1343 "Time (" unit_time ")","\\8D\\4E (" unit_energy ")",oenv);
1344 xvgr_legend(fp,asize(ravgleg),ravgleg,oenv);
1346 fprintf(stdout,"\n%-24s %10s\n",
1347 "Energy","dF = -kT ln < exp(-(EB-EA)/kT) >A");
1349 beta = 1.0/(BOLTZ*reftemp);
1350 for(i=0; i<nset; i++) {
1351 if (gmx_strcasecmp(leg[i],enm[set[i]].name)!=0)
1352 fprintf(stderr,"\nWARNING energy set name mismatch %s!=%s\n",
1353 leg[i],enm[set[i]].name);
1354 for(j=0; j<nenergy; j++) {
1355 dE = eneset2[i][j] - edat->s[i].ener[j];
1356 sum += exp(-dE*beta);
1358 fprintf(fp,"%10g %10g %10g\n",
1359 time[j], dE, -BOLTZ*reftemp*log(sum/(j+1)) );
1361 aver = -BOLTZ*reftemp*log(sum/nenergy);
1362 fprintf(stdout,"%-24s %10g\n",leg[i],aver);
1369 static void do_dhdl(t_enxframe *fr, t_inputrec *ir, FILE **fp_dhdl,
1370 const char *filename, gmx_bool bDp,
1371 int *blocks, int *hists, int *samples, int *nlambdas,
1372 const output_env_t oenv)
1374 const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
1375 char title[STRLEN],label_x[STRLEN],label_y[STRLEN], legend[STRLEN];
1377 gmx_bool first=FALSE;
1378 int nblock_hist=0, nblock_dh=0, nblock_dhcoll=0;
1381 double temp=0, start_time=0, delta_time=0, start_lambda=0, delta_lambda=0;
1383 double *native_lambda_vec=NULL;
1384 const char **lambda_components=NULL;
1386 gmx_bool changing_lambda=FALSE;
1387 int lambda_fep_state;
1389 /* now count the blocks & handle the global dh data */
1390 for(i=0;i<fr->nblock;i++)
1392 if (fr->block[i].id == enxDHHIST)
1396 else if (fr->block[i].id == enxDH)
1400 else if (fr->block[i].id == enxDHCOLL)
1403 if ( (fr->block[i].nsub < 1) ||
1404 (fr->block[i].sub[0].type != xdr_datatype_double) ||
1405 (fr->block[i].sub[0].nr < 5))
1407 gmx_fatal(FARGS, "Unexpected block data");
1410 /* read the data from the DHCOLL block */
1411 temp = fr->block[i].sub[0].dval[0];
1412 start_time = fr->block[i].sub[0].dval[1];
1413 delta_time = fr->block[i].sub[0].dval[2];
1414 start_lambda = fr->block[i].sub[0].dval[3];
1415 delta_lambda = fr->block[i].sub[0].dval[4];
1416 changing_lambda = (delta_lambda != 0);
1417 if (fr->block[i].nsub > 1)
1419 lambda_fep_state=fr->block[i].sub[1].ival[0];
1420 if (n_lambda_vec==0)
1422 n_lambda_vec=fr->block[i].sub[1].ival[1];
1426 if (n_lambda_vec!=fr->block[i].sub[1].ival[1])
1429 "Unexpected change of basis set in lambda");
1432 if (lambda_components == NULL)
1433 snew(lambda_components, n_lambda_vec);
1434 if (native_lambda_vec == NULL)
1435 snew(native_lambda_vec, n_lambda_vec);
1436 for(j=0;j<n_lambda_vec;j++)
1438 native_lambda_vec[j] = fr->block[i].sub[0].dval[5+j];
1439 lambda_components[j] =
1440 efpt_singular_names[fr->block[i].sub[1].ival[2+j]];
1446 if (nblock_hist == 0 && nblock_dh == 0)
1448 /* don't do anything */
1451 if (nblock_hist>0 && nblock_dh>0)
1453 gmx_fatal(FARGS, "This energy file contains both histogram dhdl data and non-histogram dhdl data. Don't know what to do.");
1459 /* we have standard, non-histogram data --
1460 call open_dhdl to open the file */
1461 /* TODO this is an ugly hack that needs to be fixed: this will only
1462 work if the order of data is always the same and if we're
1463 only using the g_energy compiled with the mdrun that produced
1465 *fp_dhdl=open_dhdl(filename,ir,oenv);
1469 sprintf(title,"N(%s)",deltag);
1470 sprintf(label_x,"%s (%s)",deltag,unit_energy);
1471 sprintf(label_y,"Samples");
1472 *fp_dhdl=xvgropen_type(filename, title, label_x, label_y, exvggtXNY,oenv);
1473 sprintf(buf,"T = %g (K), %s = %g", temp, lambda, start_lambda);
1474 xvgr_subtitle(*fp_dhdl,buf,oenv);
1478 (*hists)+=nblock_hist;
1479 (*blocks)+=nblock_dh;
1480 (*nlambdas) = nblock_hist+nblock_dh;
1482 /* write the data */
1483 if (nblock_hist > 0)
1485 gmx_large_int_t sum=0;
1487 for(i=0;i<fr->nblock;i++)
1489 t_enxblock *blk=&(fr->block[i]);
1490 if (blk->id==enxDHHIST)
1492 double foreign_lambda, dx;
1494 int nhist, derivative;
1496 /* check the block types etc. */
1497 if ( (blk->nsub < 2) ||
1498 (blk->sub[0].type != xdr_datatype_double) ||
1499 (blk->sub[1].type != xdr_datatype_large_int) ||
1500 (blk->sub[0].nr < 2) ||
1501 (blk->sub[1].nr < 2) )
1503 gmx_fatal(FARGS, "Unexpected block data in file");
1505 foreign_lambda=blk->sub[0].dval[0];
1506 dx=blk->sub[0].dval[1];
1507 nhist=blk->sub[1].lval[0];
1508 derivative=blk->sub[1].lval[1];
1509 for(j=0;j<nhist;j++)
1512 x0=blk->sub[1].lval[2+j];
1516 sprintf(legend, "N(%s(%s=%g) | %s=%g)",
1517 deltag, lambda, foreign_lambda,
1518 lambda, start_lambda);
1522 sprintf(legend, "N(%s | %s=%g)",
1523 dhdl, lambda, start_lambda);
1527 xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv);
1529 for(k=0;k<blk->sub[j+2].nr;k++)
1534 hist=blk->sub[j+2].ival[k];
1537 fprintf(*fp_dhdl,"%g %d\n%g %d\n", xmin, hist,
1541 /* multiple histogram data blocks in one histogram
1542 mean that the second one is the reverse of the first one:
1543 for dhdl derivatives, it's important to know both the
1544 maximum and minimum values */
1549 (*samples) += (int)(sum/nblock_hist);
1555 char **setnames=NULL;
1556 int nnames=nblock_dh;
1558 for(i=0;i<fr->nblock;i++)
1560 t_enxblock *blk=&(fr->block[i]);
1561 if (blk->id == enxDH)
1569 if (len!=blk->sub[2].nr)
1571 gmx_fatal(FARGS, "Length inconsistency in dhdl data");
1580 double time=start_time + delta_time*i;
1582 fprintf(*fp_dhdl,"%.4f ", time);
1584 for(j=0;j<fr->nblock;j++)
1586 t_enxblock *blk=&(fr->block[j]);
1587 if (blk->id == enxDH)
1590 if (blk->sub[2].type == xdr_datatype_float)
1592 value=blk->sub[2].fval[i];
1596 value=blk->sub[2].dval[i];
1598 /* we need to decide which data type it is based on the count*/
1600 if (j==1 && ir->bExpanded)
1602 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! */
1605 fprintf(*fp_dhdl," %#.12g", value); /* print normal precision */
1609 fprintf(*fp_dhdl," %#.8g", value); /* print normal precision */
1614 fprintf(*fp_dhdl, "\n");
1620 int gmx_energy(int argc,char *argv[])
1622 const char *desc[] = {
1624 "[TT]g_energy[tt] extracts energy components or distance restraint",
1625 "data from an energy file. The user is prompted to interactively",
1626 "select the desired energy terms.[PAR]",
1628 "Average, RMSD, and drift are calculated with full precision from the",
1629 "simulation (see printed manual). Drift is calculated by performing",
1630 "a least-squares fit of the data to a straight line. The reported total drift",
1631 "is the difference of the fit at the first and last point.",
1632 "An error estimate of the average is given based on a block averages",
1633 "over 5 blocks using the full-precision averages. The error estimate",
1634 "can be performed over multiple block lengths with the options",
1635 "[TT]-nbmin[tt] and [TT]-nbmax[tt].",
1636 "[BB]Note[bb] that in most cases the energy files contains averages over all",
1637 "MD steps, or over many more points than the number of frames in",
1638 "energy file. This makes the [TT]g_energy[tt] statistics output more accurate",
1639 "than the [TT].xvg[tt] output. When exact averages are not present in the energy",
1640 "file, the statistics mentioned above are simply over the single, per-frame",
1641 "energy values.[PAR]",
1643 "The term fluctuation gives the RMSD around the least-squares fit.[PAR]",
1645 "Some fluctuation-dependent properties can be calculated provided",
1646 "the correct energy terms are selected, and that the command line option",
1647 "[TT]-fluct_props[tt] is given. The following properties",
1648 "will be computed:[BR]",
1649 "Property Energy terms needed[BR]",
1650 "---------------------------------------------------[BR]",
1651 "Heat capacity C[SUB]p[sub] (NPT sims): Enthalpy, Temp [BR]",
1652 "Heat capacity C[SUB]v[sub] (NVT sims): Etot, Temp [BR]",
1653 "Thermal expansion coeff. (NPT): Enthalpy, Vol, Temp[BR]",
1654 "Isothermal compressibility: Vol, Temp [BR]",
1655 "Adiabatic bulk modulus: Vol, Temp [BR]",
1656 "---------------------------------------------------[BR]",
1657 "You always need to set the number of molecules [TT]-nmol[tt].",
1658 "The C[SUB]p[sub]/C[SUB]v[sub] computations do [BB]not[bb] include any corrections",
1659 "for quantum effects. Use the [TT]g_dos[tt] program if you need that (and you do).[PAR]"
1660 "When the [TT]-viol[tt] option is set, the time averaged",
1661 "violations are plotted and the running time-averaged and",
1662 "instantaneous sum of violations are recalculated. Additionally",
1663 "running time-averaged and instantaneous distances between",
1664 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
1666 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
1667 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
1668 "The first two options plot the orientation, the last three the",
1669 "deviations of the orientations from the experimental values.",
1670 "The options that end on an 'a' plot the average over time",
1671 "as a function of restraint. The options that end on a 't'",
1672 "prompt the user for restraint label numbers and plot the data",
1673 "as a function of time. Option [TT]-odr[tt] plots the RMS",
1674 "deviation as a function of restraint.",
1675 "When the run used time or ensemble averaged orientation restraints,",
1676 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
1677 "not ensemble-averaged orientations and deviations instead of",
1678 "the time and ensemble averages.[PAR]",
1680 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
1681 "tensor for each orientation restraint experiment. With option",
1682 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
1684 "Option [TT]-odh[tt] extracts and plots the free energy data",
1685 "(Hamiltoian differences and/or the Hamiltonian derivative dhdl)",
1686 "from the [TT]ener.edr[tt] file.[PAR]",
1688 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
1689 "difference with an ideal gas state: [BR]",
1690 " [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]",
1691 " [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]",
1692 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
1693 "the average is over the ensemble (or time in a trajectory).",
1694 "Note that this is in principle",
1695 "only correct when averaging over the whole (Boltzmann) ensemble",
1696 "and using the potential energy. This also allows for an entropy",
1697 "estimate using:[BR]",
1698 " [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]",
1699 " [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",
1702 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
1703 "difference is calculated [BR] dF = -kT [LN][CHEVRON][EXP]-(E[SUB]B[sub]-E[SUB]A[sub])/kT[exp][chevron][SUB]A[sub][ln] ,",
1704 "where E[SUB]A[sub] and E[SUB]B[sub] are the energies from the first and second energy",
1705 "files, and the average is over the ensemble A. The running average",
1706 "of the free energy difference is printed to a file specified by [TT]-ravg[tt].",
1707 "[BB]Note[bb] that the energies must both be calculated from the same trajectory."
1710 static gmx_bool bSum=FALSE,bFee=FALSE,bPrAll=FALSE,bFluct=FALSE,bDriftCorr=FALSE;
1711 static gmx_bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE,bFluctProps=FALSE;
1712 static int skip=0,nmol=1,nbmin=5,nbmax=5;
1713 static real reftemp=300.0,ezero=0;
1715 { "-fee", FALSE, etBOOL, {&bFee},
1716 "Do a free energy estimate" },
1717 { "-fetemp", FALSE, etREAL,{&reftemp},
1718 "Reference temperature for free energy calculation" },
1719 { "-zero", FALSE, etREAL, {&ezero},
1720 "Subtract a zero-point energy" },
1721 { "-sum", FALSE, etBOOL, {&bSum},
1722 "Sum the energy terms selected rather than display them all" },
1723 { "-dp", FALSE, etBOOL, {&bDp},
1724 "Print energies in high precision" },
1725 { "-nbmin", FALSE, etINT, {&nbmin},
1726 "Minimum number of blocks for error estimate" },
1727 { "-nbmax", FALSE, etINT, {&nbmax},
1728 "Maximum number of blocks for error estimate" },
1729 { "-mutot",FALSE, etBOOL, {&bMutot},
1730 "Compute the total dipole moment from the components" },
1731 { "-skip", FALSE, etINT, {&skip},
1732 "Skip number of frames between data points" },
1733 { "-aver", FALSE, etBOOL, {&bPrAll},
1734 "Also print the exact average and rmsd stored in the energy frames (only when 1 term is requested)" },
1735 { "-nmol", FALSE, etINT, {&nmol},
1736 "Number of molecules in your sample: the energies are divided by this number" },
1737 { "-fluct_props", FALSE, etBOOL, {&bFluctProps},
1738 "Compute properties based on energy fluctuations, like heat capacity" },
1739 { "-driftcorr", FALSE, etBOOL, {&bDriftCorr},
1740 "Useful only for calculations of fluctuation properties. The drift in the observables will be subtracted before computing the fluctuation properties."},
1741 { "-fluc", FALSE, etBOOL, {&bFluct},
1742 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
1743 { "-orinst", FALSE, etBOOL, {&bOrinst},
1744 "Analyse instantaneous orientation data" },
1745 { "-ovec", FALSE, etBOOL, {&bOvec},
1746 "Also plot the eigenvectors with [TT]-oten[tt]" }
1748 const char* drleg[] = {
1752 static const char *setnm[] = {
1753 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
1754 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
1755 "Volume", "Pressure"
1758 FILE *out=NULL,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
1764 gmx_localtop_t *top=NULL;
1768 gmx_enxnm_t *enm=NULL;
1769 t_enxframe *frame,*fr=NULL;
1771 #define NEXT (1-cur)
1772 int nre,teller,teller_disre,nfr;
1773 gmx_large_int_t start_step;
1774 int nor=0,nex=0,norfr=0,enx_i=0;
1776 real *bounds=NULL,*violaver=NULL,*oobs=NULL,*orient=NULL,*odrms=NULL;
1777 int *index=NULL,*pair=NULL,norsel=0,*orsel=NULL,*or_label=NULL;
1778 int nbounds=0,npairs;
1779 gmx_bool bDisRe,bDRAll,bORA,bORT,bODA,bODR,bODT,bORIRE,bOTEN,bDHDL;
1780 gmx_bool bFoundStart,bCont,bEDR,bVisco;
1781 double sum,sumaver,sumt,ener,dbl;
1784 int *set=NULL,i,j,k,nset,sss;
1785 gmx_bool *bIsEner=NULL;
1786 char **pairleg,**odtleg,**otenleg;
1789 char *anm_j,*anm_k,*resnm_j,*resnm_k;
1790 int resnr_j,resnr_k;
1791 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
1794 t_enxblock *blk=NULL;
1795 t_enxblock *blk_disre=NULL;
1797 int dh_blocks=0, dh_hists=0, dh_samples=0, dh_lambdas=0;
1800 { efEDR, "-f", NULL, ffREAD },
1801 { efEDR, "-f2", NULL, ffOPTRD },
1802 { efTPX, "-s", NULL, ffOPTRD },
1803 { efXVG, "-o", "energy", ffWRITE },
1804 { efXVG, "-viol", "violaver",ffOPTWR },
1805 { efXVG, "-pairs","pairs", ffOPTWR },
1806 { efXVG, "-ora", "orienta", ffOPTWR },
1807 { efXVG, "-ort", "orientt", ffOPTWR },
1808 { efXVG, "-oda", "orideva", ffOPTWR },
1809 { efXVG, "-odr", "oridevr", ffOPTWR },
1810 { efXVG, "-odt", "oridevt", ffOPTWR },
1811 { efXVG, "-oten", "oriten", ffOPTWR },
1812 { efXVG, "-corr", "enecorr", ffOPTWR },
1813 { efXVG, "-vis", "visco", ffOPTWR },
1814 { efXVG, "-ravg", "runavgdf",ffOPTWR },
1815 { efXVG, "-odh", "dhdl" ,ffOPTWR }
1817 #define NFILE asize(fnm)
1822 ppa = add_acf_pargs(&npargs,pa);
1823 parse_common_args(&argc,argv,
1824 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
1825 NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
1827 bDRAll = opt2bSet("-pairs",NFILE,fnm);
1828 bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
1829 bORA = opt2bSet("-ora",NFILE,fnm);
1830 bORT = opt2bSet("-ort",NFILE,fnm);
1831 bODA = opt2bSet("-oda",NFILE,fnm);
1832 bODR = opt2bSet("-odr",NFILE,fnm);
1833 bODT = opt2bSet("-odt",NFILE,fnm);
1834 bORIRE = bORA || bORT || bODA || bODR || bODT;
1835 bOTEN = opt2bSet("-oten",NFILE,fnm);
1836 bDHDL = opt2bSet("-odh",NFILE,fnm);
1841 fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
1842 do_enxnms(fp,&nre,&enm);
1846 bVisco = opt2bSet("-vis",NFILE,fnm);
1848 if ((!bDisRe) && (!bDHDL))
1853 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
1854 for(j=0; j<nset; j++) {
1855 for(i=0; i<nre; i++) {
1856 if (strstr(enm[i].name,setnm[j])) {
1862 if (gmx_strcasecmp(setnm[j],"Volume")==0) {
1863 printf("Enter the box volume (" unit_volume "): ");
1864 if(1 != scanf("%lf",&dbl))
1866 gmx_fatal(FARGS,"Error reading user input");
1870 gmx_fatal(FARGS,"Could not find term %s for viscosity calculation",
1877 set=select_by_name(nre,enm,&nset);
1879 /* Print all the different units once */
1880 sprintf(buf,"(%s)",enm[set[0]].unit);
1881 for(i=1; i<nset; i++) {
1882 for(j=0; j<i; j++) {
1883 if (strcmp(enm[set[i]].unit,enm[set[j]].unit) == 0) {
1889 strcat(buf,enm[set[i]].unit);
1893 out=xvgropen(opt2fn("-o",NFILE,fnm),"Gromacs Energies","Time (ps)",buf,
1897 for(i=0; (i<nset); i++)
1898 leg[i] = enm[set[i]].name;
1900 leg[nset]=strdup("Sum");
1901 xvgr_legend(out,nset+1,(const char**)leg,oenv);
1904 xvgr_legend(out,nset,(const char**)leg,oenv);
1907 for(i=0; (i<nset); i++) {
1909 for (j=0; (j <= F_ETOT); j++)
1910 bIsEner[i] = bIsEner[i] ||
1911 (gmx_strcasecmp(interaction_function[j].longname,leg[i]) == 0);
1914 if (bPrAll && nset > 1) {
1915 gmx_fatal(FARGS,"Printing averages can only be done when a single set is selected");
1920 if (bORIRE || bOTEN)
1921 get_orires_parms(ftp2fn(efTPX,NFILE,fnm),&nor,&nex,&or_label,&oobs);
1934 fprintf(stderr,"Select the orientation restraint labels you want (-1 is all)\n");
1935 fprintf(stderr,"End your selection with 0\n");
1941 if(1 != scanf("%d",&(orsel[j])))
1943 gmx_fatal(FARGS,"Error reading user input");
1945 } while (orsel[j] > 0);
1946 if (orsel[0] == -1) {
1947 fprintf(stderr,"Selecting all %d orientation restraints\n",nor);
1950 for(i=0; i<nor; i++)
1953 /* Build the selection */
1955 for(i=0; i<j; i++) {
1956 for(k=0; k<nor; k++)
1957 if (or_label[k] == orsel[i]) {
1963 fprintf(stderr,"Orientation restraint label %d not found\n",
1967 snew(odtleg,norsel);
1968 for(i=0; i<norsel; i++) {
1969 snew(odtleg[i],256);
1970 sprintf(odtleg[i],"%d",or_label[orsel[i]]);
1973 fort=xvgropen(opt2fn("-ort",NFILE,fnm), "Calculated orientations",
1974 "Time (ps)","",oenv);
1976 fprintf(fort,"%s",orinst_sub);
1977 xvgr_legend(fort,norsel,(const char**)odtleg,oenv);
1980 fodt=xvgropen(opt2fn("-odt",NFILE,fnm),
1981 "Orientation restraint deviation",
1982 "Time (ps)","",oenv);
1984 fprintf(fodt,"%s",orinst_sub);
1985 xvgr_legend(fodt,norsel,(const char**)odtleg,oenv);
1990 foten=xvgropen(opt2fn("-oten",NFILE,fnm),
1991 "Order tensor","Time (ps)","",oenv);
1992 snew(otenleg,bOvec ? nex*12 : nex*3);
1993 for(i=0; i<nex; i++) {
1994 for(j=0; j<3; j++) {
1995 sprintf(buf,"eig%d",j+1);
1996 otenleg[(bOvec ? 12 : 3)*i+j] = strdup(buf);
1999 for(j=0; j<9; j++) {
2000 sprintf(buf,"vec%d%s",j/3+1,j%3==0 ? "x" : (j%3==1 ? "y" : "z"));
2001 otenleg[12*i+3+j] = strdup(buf);
2005 xvgr_legend(foten,bOvec ? nex*12 : nex*3,(const char**)otenleg,oenv);
2010 nbounds=get_bounds(ftp2fn(efTPX,NFILE,fnm),&bounds,&index,&pair,&npairs,
2012 snew(violaver,npairs);
2013 out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
2014 "Time (ps)","nm",oenv);
2015 xvgr_legend(out,2,drleg,oenv);
2017 fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
2018 "Time (ps)","Distance (nm)",oenv);
2019 if (output_env_get_print_xvgr_codes(oenv))
2020 fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
2024 get_dhdl_parms(ftp2fn(efTPX,NFILE,fnm),&ir);
2027 /* Initiate energies and set them to zero */
2036 /* Initiate counters */
2039 bFoundStart = FALSE;
2043 /* This loop searches for the first frame (when -b option is given),
2044 * or when this has been found it reads just one energy frame
2047 bCont = do_enx(fp,&(frame[NEXT]));
2049 timecheck = check_times(frame[NEXT].t);
2051 } while (bCont && (timecheck < 0));
2053 if ((timecheck == 0) && bCont) {
2054 /* We read a valid frame, so we can use it */
2055 fr = &(frame[NEXT]);
2058 /* The frame contains energies, so update cur */
2061 if (edat.nframes % 1000 == 0)
2063 srenew(edat.step,edat.nframes+1000);
2064 memset(&(edat.step[edat.nframes]),0,1000*sizeof(edat.step[0]));
2065 srenew(edat.steps,edat.nframes+1000);
2066 memset(&(edat.steps[edat.nframes]),0,1000*sizeof(edat.steps[0]));
2067 srenew(edat.points,edat.nframes+1000);
2068 memset(&(edat.points[edat.nframes]),0,1000*sizeof(edat.points[0]));
2070 for(i=0; i<nset; i++)
2072 srenew(edat.s[i].ener,edat.nframes+1000);
2073 memset(&(edat.s[i].ener[edat.nframes]),0,
2074 1000*sizeof(edat.s[i].ener[0]));
2075 srenew(edat.s[i].es ,edat.nframes+1000);
2076 memset(&(edat.s[i].es[edat.nframes]),0,
2077 1000*sizeof(edat.s[i].es[0]));
2082 edat.step[nfr] = fr->step;
2087 /* Initiate the previous step data */
2088 start_step = fr->step;
2090 /* Initiate the energy sums */
2091 edat.steps[nfr] = 1;
2092 edat.points[nfr] = 1;
2093 for(i=0; i<nset; i++)
2096 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2097 edat.s[i].es[nfr].sum2 = 0;
2104 edat.steps[nfr] = fr->nsteps;
2106 if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
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;
2121 edat.points[nfr] = fr->nsum;
2122 for(i=0; i<nset; i++)
2125 edat.s[i].es[nfr].sum = fr->ener[sss].esum;
2126 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
2128 edat.npoints += fr->nsum;
2133 /* The interval does not match fr->nsteps:
2134 * can not do exact averages.
2138 edat.nsteps = fr->step - start_step + 1;
2141 for(i=0; i<nset; i++)
2143 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
2147 * Define distance restraint legends. Can only be done after
2148 * the first frame has been read... (Then we know how many there are)
2150 blk_disre=find_block_id_enxframe(fr, enxDISRE, NULL);
2151 if (bDisRe && bDRAll && !leg && blk_disre)
2156 fa = top->idef.il[F_DISRES].iatoms;
2157 ip = top->idef.iparams;
2158 if (blk_disre->nsub != 2 ||
2159 (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
2161 gmx_incons("Number of disre sub-blocks not equal to 2");
2164 ndisre=blk_disre->sub[0].nr ;
2165 if (ndisre != top->idef.il[F_DISRES].nr/3)
2167 gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
2168 ndisre,top->idef.il[F_DISRES].nr/3);
2170 snew(pairleg,ndisre);
2171 for(i=0; i<ndisre; i++)
2173 snew(pairleg[i],30);
2176 gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
2177 gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
2178 sprintf(pairleg[i],"%d %s %d %s (%d)",
2179 resnr_j,anm_j,resnr_k,anm_k,
2180 ip[fa[3*i]].disres.label);
2182 set=select_it(ndisre,pairleg,&nset);
2184 for(i=0; (i<nset); i++)
2187 sprintf(leg[2*i], "a %s",pairleg[set[i]]);
2188 snew(leg[2*i+1],32);
2189 sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
2191 xvgr_legend(fp_pairs,2*nset,(const char**)leg,oenv);
2195 * Store energies for analysis afterwards...
2197 if (!bDisRe && !bDHDL && (fr->nre > 0)) {
2198 if (edat.nframes % 1000 == 0) {
2199 srenew(time,edat.nframes+1000);
2201 time[edat.nframes] = fr->t;
2205 * Printing time, only when we do not want to skip frames
2207 if (!skip || teller % skip == 0) {
2209 /*******************************************
2210 * D I S T A N C E R E S T R A I N T S
2211 *******************************************/
2215 float *disre_rt = blk_disre->sub[0].fval;
2216 float *disre_rm3tav = blk_disre->sub[1].fval;
2218 double *disre_rt = blk_disre->sub[0].dval;
2219 double *disre_rm3tav = blk_disre->sub[1].dval;
2222 print_time(out,fr->t);
2223 if (violaver == NULL)
2224 snew(violaver,ndisre);
2226 /* Subtract bounds from distances, to calculate violations */
2227 calc_violations(disre_rt, disre_rm3tav,
2228 nbounds,pair,bounds,violaver,&sumt,&sumaver);
2230 fprintf(out," %8.4f %8.4f\n",sumaver,sumt);
2232 print_time(fp_pairs,fr->t);
2233 for(i=0; (i<nset); i++) {
2235 fprintf(fp_pairs," %8.4f", mypow(disre_rm3tav[sss],minthird));
2236 fprintf(fp_pairs," %8.4f", disre_rt[sss]);
2238 fprintf(fp_pairs,"\n");
2245 do_dhdl(fr, &ir, &fp_dhdl, opt2fn("-odh",NFILE,fnm), bDp, &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas, oenv);
2248 /*******************************************
2250 *******************************************/
2255 /* We skip frames with single points (usually only the first frame),
2256 * since they would result in an average plot with outliers.
2259 print_time(out,fr->t);
2260 print1(out,bDp,fr->ener[set[0]].e);
2261 print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
2262 print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
2268 print_time(out,fr->t);
2272 for(i=0; i<nset; i++)
2274 sum += fr->ener[set[i]].e;
2276 print1(out,bDp,sum/nmol-ezero);
2280 for(i=0; (i<nset); i++)
2284 print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
2288 print1(out,bDp,fr->ener[set[i]].e);
2295 blk = find_block_id_enxframe(fr, enx_i, NULL);
2299 xdr_datatype dt=xdr_datatype_float;
2301 xdr_datatype dt=xdr_datatype_double;
2305 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2307 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2310 vals=blk->sub[0].fval;
2312 vals=blk->sub[0].dval;
2315 if (blk->sub[0].nr != (size_t)nor)
2316 gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)", blk->sub[0].nr);
2319 for(i=0; i<nor; i++)
2320 orient[i] += vals[i];
2324 for(i=0; i<nor; i++)
2325 odrms[i] += sqr(vals[i]-oobs[i]);
2329 fprintf(fort," %10f",fr->t);
2330 for(i=0; i<norsel; i++)
2331 fprintf(fort," %g",vals[orsel[i]]);
2336 fprintf(fodt," %10f",fr->t);
2337 for(i=0; i<norsel; i++)
2338 fprintf(fodt," %g", vals[orsel[i]]-oobs[orsel[i]]);
2343 blk = find_block_id_enxframe(fr, enxORT, NULL);
2347 xdr_datatype dt=xdr_datatype_float;
2349 xdr_datatype dt=xdr_datatype_double;
2353 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2354 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2356 vals=blk->sub[0].fval;
2358 vals=blk->sub[0].dval;
2361 if (blk->sub[0].nr != (size_t)(nex*12))
2362 gmx_fatal(FARGS,"Number of orientation experiments in energy file (%g) does not match with the topology (%d)",
2363 blk->sub[0].nr/12, nex);
2364 fprintf(foten," %10f",fr->t);
2365 for(i=0; i<nex; i++)
2366 for(j=0; j<(bOvec?12:3); j++)
2367 fprintf(foten," %g",vals[i*12+j]);
2368 fprintf(foten,"\n");
2374 } while (bCont && (timecheck == 0));
2376 fprintf(stderr,"\n");
2390 out = xvgropen(opt2fn("-ora",NFILE,fnm),
2391 "Average calculated orientations",
2392 "Restraint label","",oenv);
2394 fprintf(out,"%s",orinst_sub);
2395 for(i=0; i<nor; i++)
2396 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr);
2400 out = xvgropen(opt2fn("-oda",NFILE,fnm),
2401 "Average restraint deviation",
2402 "Restraint label","",oenv);
2404 fprintf(out,"%s",orinst_sub);
2405 for(i=0; i<nor; i++)
2406 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr-oobs[i]);
2410 out = xvgropen(opt2fn("-odr",NFILE,fnm),
2411 "RMS orientation restraint deviations",
2412 "Restraint label","",oenv);
2414 fprintf(out,"%s",orinst_sub);
2415 for(i=0; i<nor; i++)
2416 fprintf(out,"%5d %g\n",or_label[i],sqrt(odrms[i]/norfr));
2424 analyse_disre(opt2fn("-viol",NFILE,fnm),
2425 teller_disre,violaver,bounds,index,pair,nbounds,oenv);
2432 printf("\n\nWrote %d lambda values with %d samples as ",
2433 dh_lambdas, dh_samples);
2436 printf("%d dH histograms ", dh_hists);
2440 printf("%d dH data blocks ", dh_blocks);
2442 printf("to %s\n", opt2fn("-odh",NFILE,fnm));
2447 gmx_fatal(FARGS, "No dH data in %s\n", opt2fn("-f",NFILE,fnm));
2453 double dt = (frame[cur].t-start_t)/(edat.nframes-1);
2454 analyse_ener(opt2bSet("-corr",NFILE,fnm),opt2fn("-corr",NFILE,fnm),
2455 bFee,bSum,bFluct,opt2parg_bSet("-nmol",npargs,ppa),
2456 bVisco,opt2fn("-vis",NFILE,fnm),
2458 start_step,start_t,frame[cur].step,frame[cur].t,
2460 nset,set,bIsEner,leg,enm,Vaver,ezero,nbmin,nbmax,
2463 calc_fluctuation_props(stdout,bDriftCorr,dt,nset,set,nmol,leg,&edat,
2466 if (opt2bSet("-f2",NFILE,fnm)) {
2467 fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
2468 reftemp, nset, set, leg, &edat, time ,oenv);
2472 const char *nxy = "-nxy";
2474 do_view(oenv,opt2fn("-o",NFILE,fnm),nxy);
2475 do_view(oenv,opt2fn_null("-ravg",NFILE,fnm),nxy);
2476 do_view(oenv,opt2fn_null("-ora",NFILE,fnm),nxy);
2477 do_view(oenv,opt2fn_null("-ort",NFILE,fnm),nxy);
2478 do_view(oenv,opt2fn_null("-oda",NFILE,fnm),nxy);
2479 do_view(oenv,opt2fn_null("-odr",NFILE,fnm),nxy);
2480 do_view(oenv,opt2fn_null("-odt",NFILE,fnm),nxy);
2481 do_view(oenv,opt2fn_null("-oten",NFILE,fnm),nxy);
2482 do_view(oenv,opt2fn_null("-odh",NFILE,fnm),nxy);