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, const char *filename, gmx_bool bDp,
1370 int *blocks, int *hists, int *samples, int *nlambdas, const output_env_t oenv)
1372 const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
1373 char title[STRLEN],label_x[STRLEN],label_y[STRLEN], legend[STRLEN];
1375 gmx_bool first=FALSE;
1376 int nblock_hist=0, nblock_dh=0, nblock_dhcoll=0;
1379 double temp=0, start_time=0, delta_time=0, start_lambda=0, delta_lambda=0;
1381 gmx_bool changing_lambda=FALSE;
1383 /* now count the blocks & handle the global dh data */
1384 for(i=0;i<fr->nblock;i++)
1386 if (fr->block[i].id == enxDHHIST)
1390 else if (fr->block[i].id == enxDH)
1394 else if (fr->block[i].id == enxDHCOLL)
1397 if ( (fr->block[i].nsub < 1) ||
1398 (fr->block[i].sub[0].type != xdr_datatype_double) ||
1399 (fr->block[i].sub[0].nr < 5))
1401 gmx_fatal(FARGS, "Unexpected block data");
1404 /* read the data from the DHCOLL block */
1405 temp = fr->block[i].sub[0].dval[0];
1406 start_time = fr->block[i].sub[0].dval[1];
1407 delta_time = fr->block[i].sub[0].dval[2];
1408 start_lambda = fr->block[i].sub[0].dval[3];
1409 delta_lambda = fr->block[i].sub[0].dval[4];
1410 changing_lambda = (delta_lambda != 0);
1414 if (nblock_hist == 0 && nblock_dh == 0)
1416 /* don't do anything */
1419 if (nblock_hist>0 && nblock_dh>0)
1421 gmx_fatal(FARGS, "This energy file contains both histogram dhdl data and non-histogram dhdl data. Don't know what to do.");
1427 /* we have standard, non-histogram data -- call open_dhdl to open the file */
1428 *fp_dhdl=open_dhdl(filename,ir,oenv);
1432 sprintf(title,"N(%s)",deltag);
1433 sprintf(label_x,"%s (%s)",deltag,unit_energy);
1434 sprintf(label_y,"Samples");
1435 *fp_dhdl=xvgropen_type(filename, title, label_x, label_y, exvggtXNY,oenv);
1436 sprintf(buf,"T = %g (K), %s = %g", temp, lambda, start_lambda);
1437 xvgr_subtitle(*fp_dhdl,buf,oenv);
1441 (*hists)+=nblock_hist;
1442 (*blocks)+=nblock_dh;
1443 (*nlambdas) = nblock_hist+nblock_dh;
1445 /* write the data */
1446 if (nblock_hist > 0)
1448 gmx_large_int_t sum=0;
1450 for(i=0;i<fr->nblock;i++)
1452 t_enxblock *blk=&(fr->block[i]);
1453 if (blk->id==enxDHHIST)
1455 double foreign_lambda, dx;
1457 int nhist, derivative;
1459 /* check the block types etc. */
1460 if ( (blk->nsub < 2) ||
1461 (blk->sub[0].type != xdr_datatype_double) ||
1462 (blk->sub[1].type != xdr_datatype_large_int) ||
1463 (blk->sub[0].nr < 2) ||
1464 (blk->sub[1].nr < 2) )
1466 gmx_fatal(FARGS, "Unexpected block data in file");
1468 foreign_lambda=blk->sub[0].dval[0];
1469 dx=blk->sub[0].dval[1];
1470 nhist=blk->sub[1].lval[0];
1471 derivative=blk->sub[1].lval[1];
1472 for(j=0;j<nhist;j++)
1475 x0=blk->sub[1].lval[2+j];
1479 sprintf(legend, "N(%s(%s=%g) | %s=%g)",
1480 deltag, lambda, foreign_lambda,
1481 lambda, start_lambda);
1485 sprintf(legend, "N(%s | %s=%g)",
1486 dhdl, lambda, start_lambda);
1490 xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv);
1492 for(k=0;k<blk->sub[j+2].nr;k++)
1497 hist=blk->sub[j+2].ival[k];
1500 fprintf(*fp_dhdl,"%g %d\n%g %d\n", xmin, hist,
1504 /* multiple histogram data blocks in one histogram
1505 mean that the second one is the reverse of the first one:
1506 for dhdl derivatives, it's important to know both the
1507 maximum and minimum values */
1512 (*samples) += (int)(sum/nblock_hist);
1518 char **setnames=NULL;
1519 int nnames=nblock_dh;
1521 for(i=0;i<fr->nblock;i++)
1523 t_enxblock *blk=&(fr->block[i]);
1524 if (blk->id == enxDH)
1532 if (len!=blk->sub[2].nr)
1534 gmx_fatal(FARGS, "Length inconsistency in dhdl data");
1543 double time=start_time + delta_time*i;
1545 fprintf(*fp_dhdl,"%.4f ", time);
1547 for(j=0;j<fr->nblock;j++)
1549 t_enxblock *blk=&(fr->block[j]);
1550 if (blk->id == enxDH)
1553 if (blk->sub[2].type == xdr_datatype_float)
1555 value=blk->sub[2].fval[i];
1559 value=blk->sub[2].dval[i];
1561 /* we need to decide which data type it is based on the count*/
1563 if (j==1 && ir->bExpanded)
1565 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! */
1568 fprintf(*fp_dhdl," %#.12g", value); /* print normal precision */
1572 fprintf(*fp_dhdl," %#.8g", value); /* print normal precision */
1577 fprintf(*fp_dhdl, "\n");
1583 int gmx_energy(int argc,char *argv[])
1585 const char *desc[] = {
1587 "[TT]g_energy[tt] extracts energy components or distance restraint",
1588 "data from an energy file. The user is prompted to interactively",
1589 "select the desired energy terms.[PAR]",
1591 "Average, RMSD, and drift are calculated with full precision from the",
1592 "simulation (see printed manual). Drift is calculated by performing",
1593 "a least-squares fit of the data to a straight line. The reported total drift",
1594 "is the difference of the fit at the first and last point.",
1595 "An error estimate of the average is given based on a block averages",
1596 "over 5 blocks using the full-precision averages. The error estimate",
1597 "can be performed over multiple block lengths with the options",
1598 "[TT]-nbmin[tt] and [TT]-nbmax[tt].",
1599 "[BB]Note[bb] that in most cases the energy files contains averages over all",
1600 "MD steps, or over many more points than the number of frames in",
1601 "energy file. This makes the [TT]g_energy[tt] statistics output more accurate",
1602 "than the [TT].xvg[tt] output. When exact averages are not present in the energy",
1603 "file, the statistics mentioned above are simply over the single, per-frame",
1604 "energy values.[PAR]",
1606 "The term fluctuation gives the RMSD around the least-squares fit.[PAR]",
1608 "Some fluctuation-dependent properties can be calculated provided",
1609 "the correct energy terms are selected, and that the command line option",
1610 "[TT]-fluct_props[tt] is given. The following properties",
1611 "will be computed:[BR]",
1612 "Property Energy terms needed[BR]",
1613 "---------------------------------------------------[BR]",
1614 "Heat capacity C[SUB]p[sub] (NPT sims): Enthalpy, Temp [BR]",
1615 "Heat capacity C[SUB]v[sub] (NVT sims): Etot, Temp [BR]",
1616 "Thermal expansion coeff. (NPT): Enthalpy, Vol, Temp[BR]",
1617 "Isothermal compressibility: Vol, Temp [BR]",
1618 "Adiabatic bulk modulus: Vol, Temp [BR]",
1619 "---------------------------------------------------[BR]",
1620 "You always need to set the number of molecules [TT]-nmol[tt].",
1621 "The C[SUB]p[sub]/C[SUB]v[sub] computations do [BB]not[bb] include any corrections",
1622 "for quantum effects. Use the [TT]g_dos[tt] program if you need that (and you do).[PAR]"
1623 "When the [TT]-viol[tt] option is set, the time averaged",
1624 "violations are plotted and the running time-averaged and",
1625 "instantaneous sum of violations are recalculated. Additionally",
1626 "running time-averaged and instantaneous distances between",
1627 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
1629 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
1630 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
1631 "The first two options plot the orientation, the last three the",
1632 "deviations of the orientations from the experimental values.",
1633 "The options that end on an 'a' plot the average over time",
1634 "as a function of restraint. The options that end on a 't'",
1635 "prompt the user for restraint label numbers and plot the data",
1636 "as a function of time. Option [TT]-odr[tt] plots the RMS",
1637 "deviation as a function of restraint.",
1638 "When the run used time or ensemble averaged orientation restraints,",
1639 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
1640 "not ensemble-averaged orientations and deviations instead of",
1641 "the time and ensemble averages.[PAR]",
1643 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
1644 "tensor for each orientation restraint experiment. With option",
1645 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
1647 "Option [TT]-odh[tt] extracts and plots the free energy data",
1648 "(Hamiltoian differences and/or the Hamiltonian derivative dhdl)",
1649 "from the [TT]ener.edr[tt] file.[PAR]",
1651 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
1652 "difference with an ideal gas state: [BR]",
1653 " [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]",
1654 " [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]",
1655 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
1656 "the average is over the ensemble (or time in a trajectory).",
1657 "Note that this is in principle",
1658 "only correct when averaging over the whole (Boltzmann) ensemble",
1659 "and using the potential energy. This also allows for an entropy",
1660 "estimate using:[BR]",
1661 " [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]",
1662 " [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",
1665 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
1666 "difference is calculated [BR] dF = -kT [LN][CHEVRON][EXP]-(E[SUB]B[sub]-E[SUB]A[sub])/kT[exp][chevron][SUB]A[sub][ln] ,",
1667 "where E[SUB]A[sub] and E[SUB]B[sub] are the energies from the first and second energy",
1668 "files, and the average is over the ensemble A. The running average",
1669 "of the free energy difference is printed to a file specified by [TT]-ravg[tt].",
1670 "[BB]Note[bb] that the energies must both be calculated from the same trajectory."
1673 static gmx_bool bSum=FALSE,bFee=FALSE,bPrAll=FALSE,bFluct=FALSE,bDriftCorr=FALSE;
1674 static gmx_bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE,bFluctProps=FALSE;
1675 static int skip=0,nmol=1,nbmin=5,nbmax=5;
1676 static real reftemp=300.0,ezero=0;
1678 { "-fee", FALSE, etBOOL, {&bFee},
1679 "Do a free energy estimate" },
1680 { "-fetemp", FALSE, etREAL,{&reftemp},
1681 "Reference temperature for free energy calculation" },
1682 { "-zero", FALSE, etREAL, {&ezero},
1683 "Subtract a zero-point energy" },
1684 { "-sum", FALSE, etBOOL, {&bSum},
1685 "Sum the energy terms selected rather than display them all" },
1686 { "-dp", FALSE, etBOOL, {&bDp},
1687 "Print energies in high precision" },
1688 { "-nbmin", FALSE, etINT, {&nbmin},
1689 "Minimum number of blocks for error estimate" },
1690 { "-nbmax", FALSE, etINT, {&nbmax},
1691 "Maximum number of blocks for error estimate" },
1692 { "-mutot",FALSE, etBOOL, {&bMutot},
1693 "Compute the total dipole moment from the components" },
1694 { "-skip", FALSE, etINT, {&skip},
1695 "Skip number of frames between data points" },
1696 { "-aver", FALSE, etBOOL, {&bPrAll},
1697 "Also print the exact average and rmsd stored in the energy frames (only when 1 term is requested)" },
1698 { "-nmol", FALSE, etINT, {&nmol},
1699 "Number of molecules in your sample: the energies are divided by this number" },
1700 { "-fluct_props", FALSE, etBOOL, {&bFluctProps},
1701 "Compute properties based on energy fluctuations, like heat capacity" },
1702 { "-driftcorr", FALSE, etBOOL, {&bDriftCorr},
1703 "Useful only for calculations of fluctuation properties. The drift in the observables will be subtracted before computing the fluctuation properties."},
1704 { "-fluc", FALSE, etBOOL, {&bFluct},
1705 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
1706 { "-orinst", FALSE, etBOOL, {&bOrinst},
1707 "Analyse instantaneous orientation data" },
1708 { "-ovec", FALSE, etBOOL, {&bOvec},
1709 "Also plot the eigenvectors with [TT]-oten[tt]" }
1711 const char* drleg[] = {
1715 static const char *setnm[] = {
1716 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
1717 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
1718 "Volume", "Pressure"
1721 FILE *out=NULL,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
1727 gmx_localtop_t *top=NULL;
1731 gmx_enxnm_t *enm=NULL;
1732 t_enxframe *frame,*fr=NULL;
1734 #define NEXT (1-cur)
1735 int nre,teller,teller_disre,nfr;
1736 gmx_large_int_t start_step;
1737 int nor=0,nex=0,norfr=0,enx_i=0;
1739 real *bounds=NULL,*violaver=NULL,*oobs=NULL,*orient=NULL,*odrms=NULL;
1740 int *index=NULL,*pair=NULL,norsel=0,*orsel=NULL,*or_label=NULL;
1741 int nbounds=0,npairs;
1742 gmx_bool bDisRe,bDRAll,bORA,bORT,bODA,bODR,bODT,bORIRE,bOTEN,bDHDL;
1743 gmx_bool bFoundStart,bCont,bEDR,bVisco;
1744 double sum,sumaver,sumt,ener,dbl;
1747 int *set=NULL,i,j,k,nset,sss;
1748 gmx_bool *bIsEner=NULL;
1749 char **pairleg,**odtleg,**otenleg;
1752 char *anm_j,*anm_k,*resnm_j,*resnm_k;
1753 int resnr_j,resnr_k;
1754 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
1757 t_enxblock *blk=NULL;
1758 t_enxblock *blk_disre=NULL;
1760 int dh_blocks=0, dh_hists=0, dh_samples=0, dh_lambdas=0;
1763 { efEDR, "-f", NULL, ffREAD },
1764 { efEDR, "-f2", NULL, ffOPTRD },
1765 { efTPX, "-s", NULL, ffOPTRD },
1766 { efXVG, "-o", "energy", ffWRITE },
1767 { efXVG, "-viol", "violaver",ffOPTWR },
1768 { efXVG, "-pairs","pairs", ffOPTWR },
1769 { efXVG, "-ora", "orienta", ffOPTWR },
1770 { efXVG, "-ort", "orientt", ffOPTWR },
1771 { efXVG, "-oda", "orideva", ffOPTWR },
1772 { efXVG, "-odr", "oridevr", ffOPTWR },
1773 { efXVG, "-odt", "oridevt", ffOPTWR },
1774 { efXVG, "-oten", "oriten", ffOPTWR },
1775 { efXVG, "-corr", "enecorr", ffOPTWR },
1776 { efXVG, "-vis", "visco", ffOPTWR },
1777 { efXVG, "-ravg", "runavgdf",ffOPTWR },
1778 { efXVG, "-odh", "dhdl" ,ffOPTWR }
1780 #define NFILE asize(fnm)
1784 CopyRight(stderr,argv[0]);
1786 ppa = add_acf_pargs(&npargs,pa);
1787 parse_common_args(&argc,argv,
1788 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
1789 NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
1791 bDRAll = opt2bSet("-pairs",NFILE,fnm);
1792 bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
1793 bORA = opt2bSet("-ora",NFILE,fnm);
1794 bORT = opt2bSet("-ort",NFILE,fnm);
1795 bODA = opt2bSet("-oda",NFILE,fnm);
1796 bODR = opt2bSet("-odr",NFILE,fnm);
1797 bODT = opt2bSet("-odt",NFILE,fnm);
1798 bORIRE = bORA || bORT || bODA || bODR || bODT;
1799 bOTEN = opt2bSet("-oten",NFILE,fnm);
1800 bDHDL = opt2bSet("-odh",NFILE,fnm);
1805 fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
1806 do_enxnms(fp,&nre,&enm);
1810 bVisco = opt2bSet("-vis",NFILE,fnm);
1812 if ((!bDisRe) && (!bDHDL))
1817 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
1818 for(j=0; j<nset; j++) {
1819 for(i=0; i<nre; i++) {
1820 if (strstr(enm[i].name,setnm[j])) {
1826 if (gmx_strcasecmp(setnm[j],"Volume")==0) {
1827 printf("Enter the box volume (" unit_volume "): ");
1828 if(1 != scanf("%lf",&dbl))
1830 gmx_fatal(FARGS,"Error reading user input");
1834 gmx_fatal(FARGS,"Could not find term %s for viscosity calculation",
1841 set=select_by_name(nre,enm,&nset);
1843 /* Print all the different units once */
1844 sprintf(buf,"(%s)",enm[set[0]].unit);
1845 for(i=1; i<nset; i++) {
1846 for(j=0; j<i; j++) {
1847 if (strcmp(enm[set[i]].unit,enm[set[j]].unit) == 0) {
1853 strcat(buf,enm[set[i]].unit);
1857 out=xvgropen(opt2fn("-o",NFILE,fnm),"Gromacs Energies","Time (ps)",buf,
1861 for(i=0; (i<nset); i++)
1862 leg[i] = enm[set[i]].name;
1864 leg[nset]=strdup("Sum");
1865 xvgr_legend(out,nset+1,(const char**)leg,oenv);
1868 xvgr_legend(out,nset,(const char**)leg,oenv);
1871 for(i=0; (i<nset); i++) {
1873 for (j=0; (j <= F_ETOT); j++)
1874 bIsEner[i] = bIsEner[i] ||
1875 (gmx_strcasecmp(interaction_function[j].longname,leg[i]) == 0);
1878 if (bPrAll && nset > 1) {
1879 gmx_fatal(FARGS,"Printing averages can only be done when a single set is selected");
1884 if (bORIRE || bOTEN)
1885 get_orires_parms(ftp2fn(efTPX,NFILE,fnm),&nor,&nex,&or_label,&oobs);
1898 fprintf(stderr,"Select the orientation restraint labels you want (-1 is all)\n");
1899 fprintf(stderr,"End your selection with 0\n");
1905 if(1 != scanf("%d",&(orsel[j])))
1907 gmx_fatal(FARGS,"Error reading user input");
1909 } while (orsel[j] > 0);
1910 if (orsel[0] == -1) {
1911 fprintf(stderr,"Selecting all %d orientation restraints\n",nor);
1914 for(i=0; i<nor; i++)
1917 /* Build the selection */
1919 for(i=0; i<j; i++) {
1920 for(k=0; k<nor; k++)
1921 if (or_label[k] == orsel[i]) {
1927 fprintf(stderr,"Orientation restraint label %d not found\n",
1931 snew(odtleg,norsel);
1932 for(i=0; i<norsel; i++) {
1933 snew(odtleg[i],256);
1934 sprintf(odtleg[i],"%d",or_label[orsel[i]]);
1937 fort=xvgropen(opt2fn("-ort",NFILE,fnm), "Calculated orientations",
1938 "Time (ps)","",oenv);
1940 fprintf(fort,"%s",orinst_sub);
1941 xvgr_legend(fort,norsel,(const char**)odtleg,oenv);
1944 fodt=xvgropen(opt2fn("-odt",NFILE,fnm),
1945 "Orientation restraint deviation",
1946 "Time (ps)","",oenv);
1948 fprintf(fodt,"%s",orinst_sub);
1949 xvgr_legend(fodt,norsel,(const char**)odtleg,oenv);
1954 foten=xvgropen(opt2fn("-oten",NFILE,fnm),
1955 "Order tensor","Time (ps)","",oenv);
1956 snew(otenleg,bOvec ? nex*12 : nex*3);
1957 for(i=0; i<nex; i++) {
1958 for(j=0; j<3; j++) {
1959 sprintf(buf,"eig%d",j+1);
1960 otenleg[(bOvec ? 12 : 3)*i+j] = strdup(buf);
1963 for(j=0; j<9; j++) {
1964 sprintf(buf,"vec%d%s",j/3+1,j%3==0 ? "x" : (j%3==1 ? "y" : "z"));
1965 otenleg[12*i+3+j] = strdup(buf);
1969 xvgr_legend(foten,bOvec ? nex*12 : nex*3,(const char**)otenleg,oenv);
1974 nbounds=get_bounds(ftp2fn(efTPX,NFILE,fnm),&bounds,&index,&pair,&npairs,
1976 snew(violaver,npairs);
1977 out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
1978 "Time (ps)","nm",oenv);
1979 xvgr_legend(out,2,drleg,oenv);
1981 fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
1982 "Time (ps)","Distance (nm)",oenv);
1983 if (output_env_get_print_xvgr_codes(oenv))
1984 fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
1988 get_dhdl_parms(ftp2fn(efTPX,NFILE,fnm),&ir);
1991 /* Initiate energies and set them to zero */
2000 /* Initiate counters */
2003 bFoundStart = FALSE;
2007 /* This loop searches for the first frame (when -b option is given),
2008 * or when this has been found it reads just one energy frame
2011 bCont = do_enx(fp,&(frame[NEXT]));
2013 timecheck = check_times(frame[NEXT].t);
2015 } while (bCont && (timecheck < 0));
2017 if ((timecheck == 0) && bCont) {
2018 /* We read a valid frame, so we can use it */
2019 fr = &(frame[NEXT]);
2022 /* The frame contains energies, so update cur */
2025 if (edat.nframes % 1000 == 0)
2027 srenew(edat.step,edat.nframes+1000);
2028 memset(&(edat.step[edat.nframes]),0,1000*sizeof(edat.step[0]));
2029 srenew(edat.steps,edat.nframes+1000);
2030 memset(&(edat.steps[edat.nframes]),0,1000*sizeof(edat.steps[0]));
2031 srenew(edat.points,edat.nframes+1000);
2032 memset(&(edat.points[edat.nframes]),0,1000*sizeof(edat.points[0]));
2034 for(i=0; i<nset; i++)
2036 srenew(edat.s[i].ener,edat.nframes+1000);
2037 memset(&(edat.s[i].ener[edat.nframes]),0,
2038 1000*sizeof(edat.s[i].ener[0]));
2039 srenew(edat.s[i].es ,edat.nframes+1000);
2040 memset(&(edat.s[i].es[edat.nframes]),0,
2041 1000*sizeof(edat.s[i].es[0]));
2046 edat.step[nfr] = fr->step;
2051 /* Initiate the previous step data */
2052 start_step = fr->step;
2054 /* Initiate the energy sums */
2055 edat.steps[nfr] = 1;
2056 edat.points[nfr] = 1;
2057 for(i=0; i<nset; i++)
2060 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2061 edat.s[i].es[nfr].sum2 = 0;
2068 edat.steps[nfr] = fr->nsteps;
2070 if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
2074 edat.points[nfr] = 1;
2075 for(i=0; i<nset; i++)
2078 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2079 edat.s[i].es[nfr].sum2 = 0;
2085 edat.points[nfr] = fr->nsum;
2086 for(i=0; i<nset; i++)
2089 edat.s[i].es[nfr].sum = fr->ener[sss].esum;
2090 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
2092 edat.npoints += fr->nsum;
2097 /* The interval does not match fr->nsteps:
2098 * can not do exact averages.
2102 edat.nsteps = fr->step - start_step + 1;
2105 for(i=0; i<nset; i++)
2107 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
2111 * Define distance restraint legends. Can only be done after
2112 * the first frame has been read... (Then we know how many there are)
2114 blk_disre=find_block_id_enxframe(fr, enxDISRE, NULL);
2115 if (bDisRe && bDRAll && !leg && blk_disre)
2120 fa = top->idef.il[F_DISRES].iatoms;
2121 ip = top->idef.iparams;
2122 if (blk_disre->nsub != 2 ||
2123 (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
2125 gmx_incons("Number of disre sub-blocks not equal to 2");
2128 ndisre=blk_disre->sub[0].nr ;
2129 if (ndisre != top->idef.il[F_DISRES].nr/3)
2131 gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
2132 ndisre,top->idef.il[F_DISRES].nr/3);
2134 snew(pairleg,ndisre);
2135 for(i=0; i<ndisre; i++)
2137 snew(pairleg[i],30);
2140 gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
2141 gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
2142 sprintf(pairleg[i],"%d %s %d %s (%d)",
2143 resnr_j,anm_j,resnr_k,anm_k,
2144 ip[fa[3*i]].disres.label);
2146 set=select_it(ndisre,pairleg,&nset);
2148 for(i=0; (i<nset); i++)
2151 sprintf(leg[2*i], "a %s",pairleg[set[i]]);
2152 snew(leg[2*i+1],32);
2153 sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
2155 xvgr_legend(fp_pairs,2*nset,(const char**)leg,oenv);
2159 * Store energies for analysis afterwards...
2161 if (!bDisRe && !bDHDL && (fr->nre > 0)) {
2162 if (edat.nframes % 1000 == 0) {
2163 srenew(time,edat.nframes+1000);
2165 time[edat.nframes] = fr->t;
2169 * Printing time, only when we do not want to skip frames
2171 if (!skip || teller % skip == 0) {
2173 /*******************************************
2174 * D I S T A N C E R E S T R A I N T S
2175 *******************************************/
2179 float *disre_rt = blk_disre->sub[0].fval;
2180 float *disre_rm3tav = blk_disre->sub[1].fval;
2182 double *disre_rt = blk_disre->sub[0].dval;
2183 double *disre_rm3tav = blk_disre->sub[1].dval;
2186 print_time(out,fr->t);
2187 if (violaver == NULL)
2188 snew(violaver,ndisre);
2190 /* Subtract bounds from distances, to calculate violations */
2191 calc_violations(disre_rt, disre_rm3tav,
2192 nbounds,pair,bounds,violaver,&sumt,&sumaver);
2194 fprintf(out," %8.4f %8.4f\n",sumaver,sumt);
2196 print_time(fp_pairs,fr->t);
2197 for(i=0; (i<nset); i++) {
2199 fprintf(fp_pairs," %8.4f", mypow(disre_rm3tav[sss],minthird));
2200 fprintf(fp_pairs," %8.4f", disre_rt[sss]);
2202 fprintf(fp_pairs,"\n");
2209 do_dhdl(fr, &ir, &fp_dhdl, opt2fn("-odh",NFILE,fnm), bDp, &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas, oenv);
2212 /*******************************************
2214 *******************************************/
2219 /* We skip frames with single points (usually only the first frame),
2220 * since they would result in an average plot with outliers.
2223 print_time(out,fr->t);
2224 print1(out,bDp,fr->ener[set[0]].e);
2225 print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
2226 print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
2232 print_time(out,fr->t);
2236 for(i=0; i<nset; i++)
2238 sum += fr->ener[set[i]].e;
2240 print1(out,bDp,sum/nmol-ezero);
2244 for(i=0; (i<nset); i++)
2248 print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
2252 print1(out,bDp,fr->ener[set[i]].e);
2259 blk = find_block_id_enxframe(fr, enx_i, NULL);
2263 xdr_datatype dt=xdr_datatype_float;
2265 xdr_datatype dt=xdr_datatype_double;
2269 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2271 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2274 vals=blk->sub[0].fval;
2276 vals=blk->sub[0].dval;
2279 if (blk->sub[0].nr != (size_t)nor)
2280 gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)", blk->sub[0].nr);
2283 for(i=0; i<nor; i++)
2284 orient[i] += vals[i];
2288 for(i=0; i<nor; i++)
2289 odrms[i] += sqr(vals[i]-oobs[i]);
2293 fprintf(fort," %10f",fr->t);
2294 for(i=0; i<norsel; i++)
2295 fprintf(fort," %g",vals[orsel[i]]);
2300 fprintf(fodt," %10f",fr->t);
2301 for(i=0; i<norsel; i++)
2302 fprintf(fodt," %g", vals[orsel[i]]-oobs[orsel[i]]);
2307 blk = find_block_id_enxframe(fr, enxORT, NULL);
2311 xdr_datatype dt=xdr_datatype_float;
2313 xdr_datatype dt=xdr_datatype_double;
2317 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2318 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2320 vals=blk->sub[0].fval;
2322 vals=blk->sub[0].dval;
2325 if (blk->sub[0].nr != (size_t)(nex*12))
2326 gmx_fatal(FARGS,"Number of orientation experiments in energy file (%g) does not match with the topology (%d)",
2327 blk->sub[0].nr/12, nex);
2328 fprintf(foten," %10f",fr->t);
2329 for(i=0; i<nex; i++)
2330 for(j=0; j<(bOvec?12:3); j++)
2331 fprintf(foten," %g",vals[i*12+j]);
2332 fprintf(foten,"\n");
2338 } while (bCont && (timecheck == 0));
2340 fprintf(stderr,"\n");
2354 out = xvgropen(opt2fn("-ora",NFILE,fnm),
2355 "Average calculated orientations",
2356 "Restraint label","",oenv);
2358 fprintf(out,"%s",orinst_sub);
2359 for(i=0; i<nor; i++)
2360 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr);
2364 out = xvgropen(opt2fn("-oda",NFILE,fnm),
2365 "Average restraint deviation",
2366 "Restraint label","",oenv);
2368 fprintf(out,"%s",orinst_sub);
2369 for(i=0; i<nor; i++)
2370 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr-oobs[i]);
2374 out = xvgropen(opt2fn("-odr",NFILE,fnm),
2375 "RMS orientation restraint deviations",
2376 "Restraint label","",oenv);
2378 fprintf(out,"%s",orinst_sub);
2379 for(i=0; i<nor; i++)
2380 fprintf(out,"%5d %g\n",or_label[i],sqrt(odrms[i]/norfr));
2388 analyse_disre(opt2fn("-viol",NFILE,fnm),
2389 teller_disre,violaver,bounds,index,pair,nbounds,oenv);
2396 printf("\n\nWrote %d lambda values with %d samples as ",
2397 dh_lambdas, dh_samples);
2400 printf("%d dH histograms ", dh_hists);
2404 printf("%d dH data blocks ", dh_blocks);
2406 printf("to %s\n", opt2fn("-odh",NFILE,fnm));
2411 gmx_fatal(FARGS, "No dH data in %s\n", opt2fn("-f",NFILE,fnm));
2417 double dt = (frame[cur].t-start_t)/(edat.nframes-1);
2418 analyse_ener(opt2bSet("-corr",NFILE,fnm),opt2fn("-corr",NFILE,fnm),
2419 bFee,bSum,bFluct,opt2parg_bSet("-nmol",npargs,ppa),
2420 bVisco,opt2fn("-vis",NFILE,fnm),
2422 start_step,start_t,frame[cur].step,frame[cur].t,
2424 nset,set,bIsEner,leg,enm,Vaver,ezero,nbmin,nbmax,
2427 calc_fluctuation_props(stdout,bDriftCorr,dt,nset,set,nmol,leg,&edat,
2430 if (opt2bSet("-f2",NFILE,fnm)) {
2431 fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
2432 reftemp, nset, set, leg, &edat, time ,oenv);
2436 const char *nxy = "-nxy";
2438 do_view(oenv,opt2fn("-o",NFILE,fnm),nxy);
2439 do_view(oenv,opt2fn_null("-ravg",NFILE,fnm),nxy);
2440 do_view(oenv,opt2fn_null("-ora",NFILE,fnm),nxy);
2441 do_view(oenv,opt2fn_null("-ort",NFILE,fnm),nxy);
2442 do_view(oenv,opt2fn_null("-oda",NFILE,fnm),nxy);
2443 do_view(oenv,opt2fn_null("-odr",NFILE,fnm),nxy);
2444 do_view(oenv,opt2fn_null("-odt",NFILE,fnm),nxy);
2445 do_view(oenv,opt2fn_null("-oten",NFILE,fnm),nxy);
2446 do_view(oenv,opt2fn_null("-odh",NFILE,fnm),nxy);