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. The following properties",
1610 "will be computed:[BR]",
1611 "Property Energy terms needed[BR]",
1612 "---------------------------------------------------[BR]",
1613 "Heat capacity C[SUB]p[sub] (NPT sims): Enthalpy, Temp [BR]",
1614 "Heat capacity C[SUB]v[sub] (NVT sims): Etot, Temp [BR]",
1615 "Thermal expansion coeff. (NPT): Enthalpy, Vol, Temp[BR]",
1616 "Isothermal compressibility: Vol, Temp [BR]",
1617 "Adiabatic bulk modulus: Vol, Temp [BR]",
1618 "---------------------------------------------------[BR]",
1619 "You always need to set the number of molecules [TT]-nmol[tt].",
1620 "The C[SUB]p[sub]/C[SUB]v[sub] computations do [BB]not[bb] include any corrections",
1621 "for quantum effects. Use the [TT]g_dos[tt] program if you need that (and you do).[PAR]"
1622 "When the [TT]-viol[tt] option is set, the time averaged",
1623 "violations are plotted and the running time-averaged and",
1624 "instantaneous sum of violations are recalculated. Additionally",
1625 "running time-averaged and instantaneous distances between",
1626 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
1628 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
1629 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
1630 "The first two options plot the orientation, the last three the",
1631 "deviations of the orientations from the experimental values.",
1632 "The options that end on an 'a' plot the average over time",
1633 "as a function of restraint. The options that end on a 't'",
1634 "prompt the user for restraint label numbers and plot the data",
1635 "as a function of time. Option [TT]-odr[tt] plots the RMS",
1636 "deviation as a function of restraint.",
1637 "When the run used time or ensemble averaged orientation restraints,",
1638 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
1639 "not ensemble-averaged orientations and deviations instead of",
1640 "the time and ensemble averages.[PAR]",
1642 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
1643 "tensor for each orientation restraint experiment. With option",
1644 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
1646 "Option [TT]-odh[tt] extracts and plots the free energy data",
1647 "(Hamiltoian differences and/or the Hamiltonian derivative dhdl)",
1648 "from the [TT]ener.edr[tt] file.[PAR]",
1650 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
1651 "difference with an ideal gas state: [BR]",
1652 " [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]",
1653 " [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]",
1654 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
1655 "the average is over the ensemble (or time in a trajectory).",
1656 "Note that this is in principle",
1657 "only correct when averaging over the whole (Boltzmann) ensemble",
1658 "and using the potential energy. This also allows for an entropy",
1659 "estimate using:[BR]",
1660 " [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]",
1661 " [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",
1664 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
1665 "difference is calculated [BR] dF = -kT [LN][CHEVRON][EXP]-(E[SUB]B[sub]-E[SUB]A[sub])/kT[exp][chevron][SUB]A[sub][ln] ,",
1666 "where E[SUB]A[sub] and E[SUB]B[sub] are the energies from the first and second energy",
1667 "files, and the average is over the ensemble A. The running average",
1668 "of the free energy difference is printed to a file specified by [TT]-ravg[tt].",
1669 "[BB]Note[bb] that the energies must both be calculated from the same trajectory."
1672 static gmx_bool bSum=FALSE,bFee=FALSE,bPrAll=FALSE,bFluct=FALSE,bDriftCorr=FALSE;
1673 static gmx_bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE;
1674 static int skip=0,nmol=1,nbmin=5,nbmax=5;
1675 static real reftemp=300.0,ezero=0;
1677 { "-fee", FALSE, etBOOL, {&bFee},
1678 "Do a free energy estimate" },
1679 { "-fetemp", FALSE, etREAL,{&reftemp},
1680 "Reference temperature for free energy calculation" },
1681 { "-zero", FALSE, etREAL, {&ezero},
1682 "Subtract a zero-point energy" },
1683 { "-sum", FALSE, etBOOL, {&bSum},
1684 "Sum the energy terms selected rather than display them all" },
1685 { "-dp", FALSE, etBOOL, {&bDp},
1686 "Print energies in high precision" },
1687 { "-nbmin", FALSE, etINT, {&nbmin},
1688 "Minimum number of blocks for error estimate" },
1689 { "-nbmax", FALSE, etINT, {&nbmax},
1690 "Maximum number of blocks for error estimate" },
1691 { "-mutot",FALSE, etBOOL, {&bMutot},
1692 "Compute the total dipole moment from the components" },
1693 { "-skip", FALSE, etINT, {&skip},
1694 "Skip number of frames between data points" },
1695 { "-aver", FALSE, etBOOL, {&bPrAll},
1696 "Also print the exact average and rmsd stored in the energy frames (only when 1 term is requested)" },
1697 { "-nmol", FALSE, etINT, {&nmol},
1698 "Number of molecules in your sample: the energies are divided by this number" },
1699 { "-driftcorr", FALSE, etBOOL, {&bDriftCorr},
1700 "Useful only for calculations of fluctuation properties. The drift in the observables will be subtracted before computing the fluctuation properties."},
1701 { "-fluc", FALSE, etBOOL, {&bFluct},
1702 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
1703 { "-orinst", FALSE, etBOOL, {&bOrinst},
1704 "Analyse instantaneous orientation data" },
1705 { "-ovec", FALSE, etBOOL, {&bOvec},
1706 "Also plot the eigenvectors with [TT]-oten[tt]" }
1708 const char* drleg[] = {
1712 static const char *setnm[] = {
1713 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
1714 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
1715 "Volume", "Pressure"
1718 FILE *out=NULL,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
1724 gmx_localtop_t *top=NULL;
1728 gmx_enxnm_t *enm=NULL;
1729 t_enxframe *frame,*fr=NULL;
1731 #define NEXT (1-cur)
1732 int nre,teller,teller_disre,nfr;
1733 gmx_large_int_t start_step;
1734 int nor=0,nex=0,norfr=0,enx_i=0;
1736 real *bounds=NULL,*violaver=NULL,*oobs=NULL,*orient=NULL,*odrms=NULL;
1737 int *index=NULL,*pair=NULL,norsel=0,*orsel=NULL,*or_label=NULL;
1738 int nbounds=0,npairs;
1739 gmx_bool bDisRe,bDRAll,bORA,bORT,bODA,bODR,bODT,bORIRE,bOTEN,bDHDL;
1740 gmx_bool bFoundStart,bCont,bEDR,bVisco;
1741 double sum,sumaver,sumt,ener,dbl;
1744 int *set=NULL,i,j,k,nset,sss;
1745 gmx_bool *bIsEner=NULL;
1746 char **pairleg,**odtleg,**otenleg;
1749 char *anm_j,*anm_k,*resnm_j,*resnm_k;
1750 int resnr_j,resnr_k;
1751 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
1754 t_enxblock *blk=NULL;
1755 t_enxblock *blk_disre=NULL;
1757 int dh_blocks=0, dh_hists=0, dh_samples=0, dh_lambdas=0;
1760 { efEDR, "-f", NULL, ffREAD },
1761 { efEDR, "-f2", NULL, ffOPTRD },
1762 { efTPX, "-s", NULL, ffOPTRD },
1763 { efXVG, "-o", "energy", ffWRITE },
1764 { efXVG, "-viol", "violaver",ffOPTWR },
1765 { efXVG, "-pairs","pairs", ffOPTWR },
1766 { efXVG, "-ora", "orienta", ffOPTWR },
1767 { efXVG, "-ort", "orientt", ffOPTWR },
1768 { efXVG, "-oda", "orideva", ffOPTWR },
1769 { efXVG, "-odr", "oridevr", ffOPTWR },
1770 { efXVG, "-odt", "oridevt", ffOPTWR },
1771 { efXVG, "-oten", "oriten", ffOPTWR },
1772 { efXVG, "-corr", "enecorr", ffOPTWR },
1773 { efXVG, "-vis", "visco", ffOPTWR },
1774 { efXVG, "-ravg", "runavgdf",ffOPTWR },
1775 { efXVG, "-odh", "dhdl" ,ffOPTWR }
1777 #define NFILE asize(fnm)
1781 CopyRight(stderr,argv[0]);
1783 ppa = add_acf_pargs(&npargs,pa);
1784 parse_common_args(&argc,argv,
1785 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
1786 NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
1788 bDRAll = opt2bSet("-pairs",NFILE,fnm);
1789 bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
1790 bORA = opt2bSet("-ora",NFILE,fnm);
1791 bORT = opt2bSet("-ort",NFILE,fnm);
1792 bODA = opt2bSet("-oda",NFILE,fnm);
1793 bODR = opt2bSet("-odr",NFILE,fnm);
1794 bODT = opt2bSet("-odt",NFILE,fnm);
1795 bORIRE = bORA || bORT || bODA || bODR || bODT;
1796 bOTEN = opt2bSet("-oten",NFILE,fnm);
1797 bDHDL = opt2bSet("-odh",NFILE,fnm);
1802 fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
1803 do_enxnms(fp,&nre,&enm);
1807 bVisco = opt2bSet("-vis",NFILE,fnm);
1809 if ((!bDisRe) && (!bDHDL))
1814 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
1815 for(j=0; j<nset; j++) {
1816 for(i=0; i<nre; i++) {
1817 if (strstr(enm[i].name,setnm[j])) {
1823 if (gmx_strcasecmp(setnm[j],"Volume")==0) {
1824 printf("Enter the box volume (" unit_volume "): ");
1825 if(1 != scanf("%lf",&dbl))
1827 gmx_fatal(FARGS,"Error reading user input");
1831 gmx_fatal(FARGS,"Could not find term %s for viscosity calculation",
1838 set=select_by_name(nre,enm,&nset);
1840 /* Print all the different units once */
1841 sprintf(buf,"(%s)",enm[set[0]].unit);
1842 for(i=1; i<nset; i++) {
1843 for(j=0; j<i; j++) {
1844 if (strcmp(enm[set[i]].unit,enm[set[j]].unit) == 0) {
1850 strcat(buf,enm[set[i]].unit);
1854 out=xvgropen(opt2fn("-o",NFILE,fnm),"Gromacs Energies","Time (ps)",buf,
1858 for(i=0; (i<nset); i++)
1859 leg[i] = enm[set[i]].name;
1861 leg[nset]=strdup("Sum");
1862 xvgr_legend(out,nset+1,(const char**)leg,oenv);
1865 xvgr_legend(out,nset,(const char**)leg,oenv);
1868 for(i=0; (i<nset); i++) {
1870 for (j=0; (j <= F_ETOT); j++)
1871 bIsEner[i] = bIsEner[i] ||
1872 (gmx_strcasecmp(interaction_function[j].longname,leg[i]) == 0);
1875 if (bPrAll && nset > 1) {
1876 gmx_fatal(FARGS,"Printing averages can only be done when a single set is selected");
1881 if (bORIRE || bOTEN)
1882 get_orires_parms(ftp2fn(efTPX,NFILE,fnm),&nor,&nex,&or_label,&oobs);
1895 fprintf(stderr,"Select the orientation restraint labels you want (-1 is all)\n");
1896 fprintf(stderr,"End your selection with 0\n");
1902 if(1 != scanf("%d",&(orsel[j])))
1904 gmx_fatal(FARGS,"Error reading user input");
1906 } while (orsel[j] > 0);
1907 if (orsel[0] == -1) {
1908 fprintf(stderr,"Selecting all %d orientation restraints\n",nor);
1911 for(i=0; i<nor; i++)
1914 /* Build the selection */
1916 for(i=0; i<j; i++) {
1917 for(k=0; k<nor; k++)
1918 if (or_label[k] == orsel[i]) {
1924 fprintf(stderr,"Orientation restraint label %d not found\n",
1928 snew(odtleg,norsel);
1929 for(i=0; i<norsel; i++) {
1930 snew(odtleg[i],256);
1931 sprintf(odtleg[i],"%d",or_label[orsel[i]]);
1934 fort=xvgropen(opt2fn("-ort",NFILE,fnm), "Calculated orientations",
1935 "Time (ps)","",oenv);
1937 fprintf(fort,"%s",orinst_sub);
1938 xvgr_legend(fort,norsel,(const char**)odtleg,oenv);
1941 fodt=xvgropen(opt2fn("-odt",NFILE,fnm),
1942 "Orientation restraint deviation",
1943 "Time (ps)","",oenv);
1945 fprintf(fodt,"%s",orinst_sub);
1946 xvgr_legend(fodt,norsel,(const char**)odtleg,oenv);
1951 foten=xvgropen(opt2fn("-oten",NFILE,fnm),
1952 "Order tensor","Time (ps)","",oenv);
1953 snew(otenleg,bOvec ? nex*12 : nex*3);
1954 for(i=0; i<nex; i++) {
1955 for(j=0; j<3; j++) {
1956 sprintf(buf,"eig%d",j+1);
1957 otenleg[(bOvec ? 12 : 3)*i+j] = strdup(buf);
1960 for(j=0; j<9; j++) {
1961 sprintf(buf,"vec%d%s",j/3+1,j%3==0 ? "x" : (j%3==1 ? "y" : "z"));
1962 otenleg[12*i+3+j] = strdup(buf);
1966 xvgr_legend(foten,bOvec ? nex*12 : nex*3,(const char**)otenleg,oenv);
1971 nbounds=get_bounds(ftp2fn(efTPX,NFILE,fnm),&bounds,&index,&pair,&npairs,
1973 snew(violaver,npairs);
1974 out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
1975 "Time (ps)","nm",oenv);
1976 xvgr_legend(out,2,drleg,oenv);
1978 fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
1979 "Time (ps)","Distance (nm)",oenv);
1980 if (output_env_get_print_xvgr_codes(oenv))
1981 fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
1985 get_dhdl_parms(ftp2fn(efTPX,NFILE,fnm),&ir);
1988 /* Initiate energies and set them to zero */
1997 /* Initiate counters */
2000 bFoundStart = FALSE;
2004 /* This loop searches for the first frame (when -b option is given),
2005 * or when this has been found it reads just one energy frame
2008 bCont = do_enx(fp,&(frame[NEXT]));
2010 timecheck = check_times(frame[NEXT].t);
2012 } while (bCont && (timecheck < 0));
2014 if ((timecheck == 0) && bCont) {
2015 /* We read a valid frame, so we can use it */
2016 fr = &(frame[NEXT]);
2019 /* The frame contains energies, so update cur */
2022 if (edat.nframes % 1000 == 0)
2024 srenew(edat.step,edat.nframes+1000);
2025 memset(&(edat.step[edat.nframes]),0,1000*sizeof(edat.step[0]));
2026 srenew(edat.steps,edat.nframes+1000);
2027 memset(&(edat.steps[edat.nframes]),0,1000*sizeof(edat.steps[0]));
2028 srenew(edat.points,edat.nframes+1000);
2029 memset(&(edat.points[edat.nframes]),0,1000*sizeof(edat.points[0]));
2031 for(i=0; i<nset; i++)
2033 srenew(edat.s[i].ener,edat.nframes+1000);
2034 memset(&(edat.s[i].ener[edat.nframes]),0,
2035 1000*sizeof(edat.s[i].ener[0]));
2036 srenew(edat.s[i].es ,edat.nframes+1000);
2037 memset(&(edat.s[i].es[edat.nframes]),0,
2038 1000*sizeof(edat.s[i].es[0]));
2043 edat.step[nfr] = fr->step;
2048 /* Initiate the previous step data */
2049 start_step = fr->step;
2051 /* Initiate the energy sums */
2052 edat.steps[nfr] = 1;
2053 edat.points[nfr] = 1;
2054 for(i=0; i<nset; i++)
2057 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2058 edat.s[i].es[nfr].sum2 = 0;
2065 edat.steps[nfr] = fr->nsteps;
2067 if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
2071 edat.points[nfr] = 1;
2072 for(i=0; i<nset; i++)
2075 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2076 edat.s[i].es[nfr].sum2 = 0;
2082 edat.points[nfr] = fr->nsum;
2083 for(i=0; i<nset; i++)
2086 edat.s[i].es[nfr].sum = fr->ener[sss].esum;
2087 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
2089 edat.npoints += fr->nsum;
2094 /* The interval does not match fr->nsteps:
2095 * can not do exact averages.
2099 edat.nsteps = fr->step - start_step + 1;
2102 for(i=0; i<nset; i++)
2104 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
2108 * Define distance restraint legends. Can only be done after
2109 * the first frame has been read... (Then we know how many there are)
2111 blk_disre=find_block_id_enxframe(fr, enxDISRE, NULL);
2112 if (bDisRe && bDRAll && !leg && blk_disre)
2117 fa = top->idef.il[F_DISRES].iatoms;
2118 ip = top->idef.iparams;
2119 if (blk_disre->nsub != 2 ||
2120 (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
2122 gmx_incons("Number of disre sub-blocks not equal to 2");
2125 ndisre=blk_disre->sub[0].nr ;
2126 if (ndisre != top->idef.il[F_DISRES].nr/3)
2128 gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
2129 ndisre,top->idef.il[F_DISRES].nr/3);
2131 snew(pairleg,ndisre);
2132 for(i=0; i<ndisre; i++)
2134 snew(pairleg[i],30);
2137 gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
2138 gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
2139 sprintf(pairleg[i],"%d %s %d %s (%d)",
2140 resnr_j,anm_j,resnr_k,anm_k,
2141 ip[fa[3*i]].disres.label);
2143 set=select_it(ndisre,pairleg,&nset);
2145 for(i=0; (i<nset); i++)
2148 sprintf(leg[2*i], "a %s",pairleg[set[i]]);
2149 snew(leg[2*i+1],32);
2150 sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
2152 xvgr_legend(fp_pairs,2*nset,(const char**)leg,oenv);
2156 * Store energies for analysis afterwards...
2158 if (!bDisRe && !bDHDL && (fr->nre > 0)) {
2159 if (edat.nframes % 1000 == 0) {
2160 srenew(time,edat.nframes+1000);
2162 time[edat.nframes] = fr->t;
2166 * Printing time, only when we do not want to skip frames
2168 if (!skip || teller % skip == 0) {
2170 /*******************************************
2171 * D I S T A N C E R E S T R A I N T S
2172 *******************************************/
2176 float *disre_rt = blk_disre->sub[0].fval;
2177 float *disre_rm3tav = blk_disre->sub[1].fval;
2179 double *disre_rt = blk_disre->sub[0].dval;
2180 double *disre_rm3tav = blk_disre->sub[1].dval;
2183 print_time(out,fr->t);
2184 if (violaver == NULL)
2185 snew(violaver,ndisre);
2187 /* Subtract bounds from distances, to calculate violations */
2188 calc_violations(disre_rt, disre_rm3tav,
2189 nbounds,pair,bounds,violaver,&sumt,&sumaver);
2191 fprintf(out," %8.4f %8.4f\n",sumaver,sumt);
2193 print_time(fp_pairs,fr->t);
2194 for(i=0; (i<nset); i++) {
2196 fprintf(fp_pairs," %8.4f", mypow(disre_rm3tav[sss],minthird));
2197 fprintf(fp_pairs," %8.4f", disre_rt[sss]);
2199 fprintf(fp_pairs,"\n");
2206 do_dhdl(fr, &ir, &fp_dhdl, opt2fn("-odh",NFILE,fnm), bDp, &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas, oenv);
2209 /*******************************************
2211 *******************************************/
2216 /* We skip frames with single points (usually only the first frame),
2217 * since they would result in an average plot with outliers.
2220 print_time(out,fr->t);
2221 print1(out,bDp,fr->ener[set[0]].e);
2222 print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
2223 print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
2229 print_time(out,fr->t);
2233 for(i=0; i<nset; i++)
2235 sum += fr->ener[set[i]].e;
2237 print1(out,bDp,sum/nmol-ezero);
2241 for(i=0; (i<nset); i++)
2245 print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
2249 print1(out,bDp,fr->ener[set[i]].e);
2256 blk = find_block_id_enxframe(fr, enx_i, NULL);
2260 xdr_datatype dt=xdr_datatype_float;
2262 xdr_datatype dt=xdr_datatype_double;
2266 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2268 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2271 vals=blk->sub[0].fval;
2273 vals=blk->sub[0].dval;
2276 if (blk->sub[0].nr != (size_t)nor)
2277 gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)", blk->sub[0].nr);
2280 for(i=0; i<nor; i++)
2281 orient[i] += vals[i];
2285 for(i=0; i<nor; i++)
2286 odrms[i] += sqr(vals[i]-oobs[i]);
2290 fprintf(fort," %10f",fr->t);
2291 for(i=0; i<norsel; i++)
2292 fprintf(fort," %g",vals[orsel[i]]);
2297 fprintf(fodt," %10f",fr->t);
2298 for(i=0; i<norsel; i++)
2299 fprintf(fodt," %g", vals[orsel[i]]-oobs[orsel[i]]);
2304 blk = find_block_id_enxframe(fr, enxORT, NULL);
2308 xdr_datatype dt=xdr_datatype_float;
2310 xdr_datatype dt=xdr_datatype_double;
2314 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2315 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2317 vals=blk->sub[0].fval;
2319 vals=blk->sub[0].dval;
2322 if (blk->sub[0].nr != (size_t)(nex*12))
2323 gmx_fatal(FARGS,"Number of orientation experiments in energy file (%g) does not match with the topology (%d)",
2324 blk->sub[0].nr/12, nex);
2325 fprintf(foten," %10f",fr->t);
2326 for(i=0; i<nex; i++)
2327 for(j=0; j<(bOvec?12:3); j++)
2328 fprintf(foten," %g",vals[i*12+j]);
2329 fprintf(foten,"\n");
2335 } while (bCont && (timecheck == 0));
2337 fprintf(stderr,"\n");
2351 out = xvgropen(opt2fn("-ora",NFILE,fnm),
2352 "Average calculated orientations",
2353 "Restraint label","",oenv);
2355 fprintf(out,"%s",orinst_sub);
2356 for(i=0; i<nor; i++)
2357 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr);
2361 out = xvgropen(opt2fn("-oda",NFILE,fnm),
2362 "Average restraint deviation",
2363 "Restraint label","",oenv);
2365 fprintf(out,"%s",orinst_sub);
2366 for(i=0; i<nor; i++)
2367 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr-oobs[i]);
2371 out = xvgropen(opt2fn("-odr",NFILE,fnm),
2372 "RMS orientation restraint deviations",
2373 "Restraint label","",oenv);
2375 fprintf(out,"%s",orinst_sub);
2376 for(i=0; i<nor; i++)
2377 fprintf(out,"%5d %g\n",or_label[i],sqrt(odrms[i]/norfr));
2385 analyse_disre(opt2fn("-viol",NFILE,fnm),
2386 teller_disre,violaver,bounds,index,pair,nbounds,oenv);
2393 printf("\n\nWrote %d lambda values with %d samples as ",
2394 dh_lambdas, dh_samples);
2397 printf("%d dH histograms ", dh_hists);
2401 printf("%d dH data blocks ", dh_blocks);
2403 printf("to %s\n", opt2fn("-odh",NFILE,fnm));
2408 gmx_fatal(FARGS, "No dH data in %s\n", opt2fn("-f",NFILE,fnm));
2414 double dt = (frame[cur].t-start_t)/(edat.nframes-1);
2415 analyse_ener(opt2bSet("-corr",NFILE,fnm),opt2fn("-corr",NFILE,fnm),
2416 bFee,bSum,bFluct,opt2parg_bSet("-nmol",npargs,ppa),
2417 bVisco,opt2fn("-vis",NFILE,fnm),
2419 start_step,start_t,frame[cur].step,frame[cur].t,
2421 nset,set,bIsEner,leg,enm,Vaver,ezero,nbmin,nbmax,
2423 calc_fluctuation_props(stdout,bDriftCorr,dt,nset,set,nmol,leg,&edat,
2426 if (opt2bSet("-f2",NFILE,fnm)) {
2427 fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
2428 reftemp, nset, set, leg, &edat, time ,oenv);
2432 const char *nxy = "-nxy";
2434 do_view(oenv,opt2fn("-o",NFILE,fnm),nxy);
2435 do_view(oenv,opt2fn_null("-ravg",NFILE,fnm),nxy);
2436 do_view(oenv,opt2fn_null("-ora",NFILE,fnm),nxy);
2437 do_view(oenv,opt2fn_null("-ort",NFILE,fnm),nxy);
2438 do_view(oenv,opt2fn_null("-oda",NFILE,fnm),nxy);
2439 do_view(oenv,opt2fn_null("-odr",NFILE,fnm),nxy);
2440 do_view(oenv,opt2fn_null("-odt",NFILE,fnm),nxy);
2441 do_view(oenv,opt2fn_null("-oten",NFILE,fnm),nxy);
2442 do_view(oenv,opt2fn_null("-odh",NFILE,fnm),nxy);