2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
45 #include "gromacs/commandline/pargs.h"
46 #include "gromacs/correlationfunctions/autocorr.h"
47 #include "gromacs/fileio/enxio.h"
48 #include "gromacs/fileio/gmxfio.h"
49 #include "gromacs/fileio/tpxio.h"
50 #include "gromacs/fileio/trxio.h"
51 #include "gromacs/fileio/xvgr.h"
52 #include "gromacs/gmxana/gmx_ana.h"
53 #include "gromacs/gmxana/gstat.h"
54 #include "gromacs/legacyheaders/copyrite.h"
55 #include "gromacs/legacyheaders/macros.h"
56 #include "gromacs/legacyheaders/mdebin.h"
57 #include "gromacs/legacyheaders/names.h"
58 #include "gromacs/legacyheaders/typedefs.h"
59 #include "gromacs/legacyheaders/viewit.h"
60 #include "gromacs/math/units.h"
61 #include "gromacs/math/vec.h"
62 #include "gromacs/topology/mtop_util.h"
63 #include "gromacs/utility/cstringutil.h"
64 #include "gromacs/utility/fatalerror.h"
65 #include "gromacs/utility/gmxassert.h"
66 #include "gromacs/utility/smalloc.h"
68 static real minthird = -1.0/3.0, minsixth = -1.0/6.0;
96 static double mypow(double x, double y)
100 return std::pow(x, y);
108 static int *select_it(int nre, char *nm[], int *nset)
113 gmx_bool bVerbose = TRUE;
115 if ((getenv("GMX_ENER_VERBOSE")) != NULL)
120 fprintf(stderr, "Select the terms you want from the following list\n");
121 fprintf(stderr, "End your selection with 0\n");
125 for (k = 0; (k < nre); )
127 for (j = 0; (j < 4) && (k < nre); j++, k++)
129 fprintf(stderr, " %3d=%14s", k+1, nm[k]);
131 fprintf(stderr, "\n");
138 if (1 != scanf("%d", &n))
140 gmx_fatal(FARGS, "Error reading user input");
142 if ((n > 0) && (n <= nre))
150 for (i = (*nset) = 0; (i < nre); i++)
163 static void chomp(char *buf)
165 int len = std::strlen(buf);
167 while ((len > 0) && (buf[len-1] == '\n'))
174 static int *select_by_name(int nre, gmx_enxnm_t *nm, int *nset)
177 int k, kk, j, i, nmatch, nind, nss;
179 gmx_bool bEOF, bVerbose = TRUE, bLong = FALSE;
180 char *ptr, buf[STRLEN];
181 const char *fm4 = "%3d %-14s";
182 const char *fm2 = "%3d %-34s";
185 if ((getenv("GMX_ENER_VERBOSE")) != NULL)
190 fprintf(stderr, "\n");
191 fprintf(stderr, "Select the terms you want from the following list by\n");
192 fprintf(stderr, "selecting either (part of) the name or the number or a combination.\n");
193 fprintf(stderr, "End your selection with an empty line or a zero.\n");
194 fprintf(stderr, "-------------------------------------------------------------------\n");
198 for (k = 0; k < nre; k++)
200 newnm[k] = gmx_strdup(nm[k].name);
201 /* Insert dashes in all the names */
202 while ((ptr = std::strchr(newnm[k], ' ')) != NULL)
212 fprintf(stderr, "\n");
215 for (kk = k; kk < k+4; kk++)
217 if (kk < nre && std::strlen(nm[kk].name) > 14)
225 fprintf(stderr, " ");
229 fprintf(stderr, fm4, k+1, newnm[k]);
238 fprintf(stderr, fm2, k+1, newnm[k]);
249 fprintf(stderr, "\n\n");
255 while (!bEOF && (fgets2(buf, STRLEN-1, stdin)))
257 /* Remove newlines */
263 /* Empty line means end of input */
264 bEOF = (std::strlen(buf) == 0);
272 /* First try to read an integer */
273 nss = sscanf(ptr, "%d", &nind);
276 /* Zero means end of input */
281 else if ((1 <= nind) && (nind <= nre))
287 fprintf(stderr, "number %d is out of range\n", nind);
292 /* Now try to read a string */
294 for (nind = 0; nind < nre; nind++)
296 if (gmx_strcasecmp(newnm[nind], ptr) == 0)
304 i = std::strlen(ptr);
306 for (nind = 0; nind < nre; nind++)
308 if (gmx_strncasecmp(newnm[nind], ptr, i) == 0)
316 fprintf(stderr, "String '%s' does not match anything\n", ptr);
321 /* Look for the first space, and remove spaces from there */
322 if ((ptr = std::strchr(ptr, ' ')) != NULL)
327 while (!bEOF && (ptr && (std::strlen(ptr) > 0)));
332 for (i = (*nset) = 0; (i < nre); i++)
344 gmx_fatal(FARGS, "No energy terms selected");
347 for (i = 0; (i < nre); i++)
356 static void get_dhdl_parms(const char *topnm, t_inputrec *ir)
362 /* all we need is the ir to be able to write the label */
363 read_tpx(topnm, ir, box, &natoms, NULL, NULL, NULL, &mtop);
366 static void get_orires_parms(const char *topnm,
367 int *nor, int *nex, int **label, real **obs)
378 read_tpx(topnm, &ir, box, &natoms, NULL, NULL, NULL, &mtop);
379 top = gmx_mtop_generate_local_top(&mtop, &ir);
381 ip = top->idef.iparams;
382 iatom = top->idef.il[F_ORIRES].iatoms;
384 /* Count how many distance restraint there are... */
385 nb = top->idef.il[F_ORIRES].nr;
388 gmx_fatal(FARGS, "No orientation restraints in topology!\n");
395 for (i = 0; i < nb; i += 3)
397 (*label)[i/3] = ip[iatom[i]].orires.label;
398 (*obs)[i/3] = ip[iatom[i]].orires.obs;
399 if (ip[iatom[i]].orires.ex >= *nex)
401 *nex = ip[iatom[i]].orires.ex+1;
404 fprintf(stderr, "Found %d orientation restraints with %d experiments",
408 static int get_bounds(const char *topnm,
409 real **bounds, int **index, int **dr_pair, int *npairs,
410 gmx_mtop_t *mtop, gmx_localtop_t **ltop, t_inputrec *ir)
413 t_functype *functype;
415 int natoms, i, j, k, type, ftype, natom;
423 read_tpx(topnm, ir, box, &natoms, NULL, NULL, NULL, mtop);
425 top = gmx_mtop_generate_local_top(mtop, ir);
428 functype = top->idef.functype;
429 ip = top->idef.iparams;
431 /* Count how many distance restraint there are... */
432 nb = top->idef.il[F_DISRES].nr;
435 gmx_fatal(FARGS, "No distance restraints in topology!\n");
438 /* Allocate memory */
443 /* Fill the bound array */
445 for (i = 0; (i < top->idef.ntypes); i++)
448 if (ftype == F_DISRES)
451 label1 = ip[i].disres.label;
452 b[nb] = ip[i].disres.up1;
459 /* Fill the index array */
461 disres = &(top->idef.il[F_DISRES]);
462 iatom = disres->iatoms;
463 for (i = j = k = 0; (i < disres->nr); )
466 ftype = top->idef.functype[type];
467 natom = interaction_function[ftype].nratoms+1;
468 if (label1 != top->idef.iparams[type].disres.label)
471 label1 = top->idef.iparams[type].disres.label;
481 gmx_incons("get_bounds for distance restraints");
490 static void calc_violations(real rt[], real rav3[], int nb, int index[],
491 real bounds[], real *viol, double *st, double *sa)
493 const real sixth = 1.0/6.0;
495 double rsum, rav, sumaver, sumt;
499 for (i = 0; (i < nb); i++)
503 for (j = index[i]; (j < index[i+1]); j++)
507 viol[j] += mypow(rt[j], -3.0);
510 rsum += mypow(rt[j], -6);
512 rsum = std::max(0.0, mypow(rsum, -sixth)-bounds[i]);
513 rav = std::max(0.0, mypow(rav, -sixth)-bounds[i]);
522 static void analyse_disre(const char *voutfn, int nframes,
523 real violaver[], real bounds[], int index[],
524 int pair[], int nbounds,
525 const output_env_t oenv)
528 double sum, sumt, sumaver;
531 /* Subtract bounds from distances, to calculate violations */
532 calc_violations(violaver, violaver,
533 nbounds, pair, bounds, NULL, &sumt, &sumaver);
536 fprintf(stdout, "\nSum of violations averaged over simulation: %g nm\n",
538 fprintf(stdout, "Largest violation averaged over simulation: %g nm\n\n",
541 vout = xvgropen(voutfn, "r\\S-3\\N average violations", "DR Index", "nm",
545 for (i = 0; (i < nbounds); i++)
547 /* Do ensemble averaging */
549 for (j = pair[i]; (j < pair[i+1]); j++)
551 sumaver += sqr(violaver[j]/nframes);
553 sumaver = std::max(0.0, mypow(sumaver, minsixth)-bounds[i]);
556 sum = std::max(sum, sumaver);
557 fprintf(vout, "%10d %10.5e\n", index[i], sumaver);
560 for (j = 0; (j < dr.ndr); j++)
562 fprintf(vout, "%10d %10.5e\n", j, mypow(violaver[j]/nframes, minthird));
567 fprintf(stdout, "\nSum of violations averaged over simulation: %g nm\n",
569 fprintf(stdout, "Largest violation averaged over simulation: %g nm\n\n", sum);
571 do_view(oenv, voutfn, "-graphtype bar");
574 static void einstein_visco(const char *fn, const char *fni, int nsets,
575 int nint, real **eneint,
576 real V, real T, double dt,
577 const output_env_t oenv)
580 double av[4], avold[4];
586 for (i = 0; i <= nsets; i++)
590 fp0 = xvgropen(fni, "Shear viscosity integral",
591 "Time (ps)", "(kg m\\S-1\\N s\\S-1\\N ps)", oenv);
592 fp1 = xvgropen(fn, "Shear viscosity using Einstein relation",
593 "Time (ps)", "(kg m\\S-1\\N s\\S-1\\N)", oenv);
594 for (i = 0; i < nf4; i++)
596 for (m = 0; m <= nsets; m++)
600 for (j = 0; j < nint - i; j++)
602 for (m = 0; m < nsets; m++)
604 di = sqr(eneint[m][j+i] - eneint[m][j]);
607 av[nsets] += di/nsets;
610 /* Convert to SI for the viscosity */
611 fac = (V*NANO*NANO*NANO*PICO*1e10)/(2*BOLTZMANN*T)/(nint - i);
612 fprintf(fp0, "%10g", i*dt);
613 for (m = 0; (m <= nsets); m++)
616 fprintf(fp0, " %10g", av[m]);
619 fprintf(fp1, "%10g", (i + 0.5)*dt);
620 for (m = 0; (m <= nsets); m++)
622 fprintf(fp1, " %10g", (av[m]-avold[m])/dt);
645 static void clear_ee_sum(ee_sum_t *ees)
653 static void add_ee_sum(ee_sum_t *ees, double sum, int np)
659 static void add_ee_av(ee_sum_t *ees)
663 av = ees->sum/ees->np;
670 static double calc_ee2(int nb, ee_sum_t *ees)
672 return (ees->sav2/nb - dsqr(ees->sav/nb))/(nb - 1);
675 static void set_ee_av(ener_ee_t *eee)
679 char buf[STEPSTRSIZE];
680 fprintf(debug, "Storing average for err.est.: %s steps\n",
681 gmx_step_str(eee->nst, buf));
683 add_ee_av(&eee->sum);
685 if (eee->b == 1 || eee->nst < eee->nst_min)
687 eee->nst_min = eee->nst;
692 static void calc_averages(int nset, enerdata_t *edat, int nbmin, int nbmax)
695 double sum, sum2, sump, see2;
696 gmx_int64_t np, p, bound_nb;
700 double x, sx, sy, sxx, sxy;
703 /* Check if we have exact statistics over all points */
704 for (i = 0; i < nset; i++)
707 ed->bExactStat = FALSE;
710 /* All energy file sum entries 0 signals no exact sums.
711 * But if all energy values are 0, we still have exact sums.
714 for (f = 0; f < edat->nframes && !ed->bExactStat; f++)
716 if (ed->ener[i] != 0)
720 ed->bExactStat = (ed->es[f].sum != 0);
724 ed->bExactStat = TRUE;
730 for (i = 0; i < nset; i++)
741 for (nb = nbmin; nb <= nbmax; nb++)
744 clear_ee_sum(&eee[nb].sum);
748 for (f = 0; f < edat->nframes; f++)
754 /* Add the sum and the sum of variances to the totals. */
760 sum2 += dsqr(sum/np - (sum + es->sum)/(np + p))
766 /* Add a single value to the sum and sum of squares. */
772 /* sum has to be increased after sum2 */
776 /* For the linear regression use variance 1/p.
777 * Note that sump is the sum, not the average, so we don't need p*.
779 x = edat->step[f] - 0.5*(edat->steps[f] - 1);
785 for (nb = nbmin; nb <= nbmax; nb++)
787 /* Check if the current end step is closer to the desired
788 * block boundary than the next end step.
790 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
791 if (eee[nb].nst > 0 &&
792 bound_nb - edat->step[f-1]*nb < edat->step[f]*nb - bound_nb)
802 eee[nb].nst += edat->step[f] - edat->step[f-1];
806 add_ee_sum(&eee[nb].sum, es->sum, edat->points[f]);
810 add_ee_sum(&eee[nb].sum, edat->s[i].ener[f], 1);
812 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
813 if (edat->step[f]*nb >= bound_nb)
820 edat->s[i].av = sum/np;
823 edat->s[i].rmsd = std::sqrt(sum2/np);
827 edat->s[i].rmsd = std::sqrt(sum2/np - dsqr(edat->s[i].av));
830 if (edat->nframes > 1)
832 edat->s[i].slope = (np*sxy - sx*sy)/(np*sxx - sx*sx);
836 edat->s[i].slope = 0;
841 for (nb = nbmin; nb <= nbmax; nb++)
843 /* Check if we actually got nb blocks and if the smallest
844 * block is not shorter than 80% of the average.
848 char buf1[STEPSTRSIZE], buf2[STEPSTRSIZE];
849 fprintf(debug, "Requested %d blocks, we have %d blocks, min %s nsteps %s\n",
851 gmx_step_str(eee[nb].nst_min, buf1),
852 gmx_step_str(edat->nsteps, buf2));
854 if (eee[nb].b == nb && 5*nb*eee[nb].nst_min >= 4*edat->nsteps)
856 see2 += calc_ee2(nb, &eee[nb].sum);
862 edat->s[i].ee = std::sqrt(see2/nee);
872 static enerdata_t *calc_sum(int nset, enerdata_t *edat, int nbmin, int nbmax)
883 snew(s->ener, esum->nframes);
884 snew(s->es, esum->nframes);
886 s->bExactStat = TRUE;
888 for (i = 0; i < nset; i++)
890 if (!edat->s[i].bExactStat)
892 s->bExactStat = FALSE;
894 s->slope += edat->s[i].slope;
897 for (f = 0; f < edat->nframes; f++)
900 for (i = 0; i < nset; i++)
902 sum += edat->s[i].ener[f];
906 for (i = 0; i < nset; i++)
908 sum += edat->s[i].es[f].sum;
914 calc_averages(1, esum, nbmin, nbmax);
919 static char *ee_pr(double ee, char *buf)
926 sprintf(buf, "%s", "--");
930 /* Round to two decimals by printing. */
931 sprintf(tmp, "%.1e", ee);
932 sscanf(tmp, "%lf", &rnd);
933 sprintf(buf, "%g", rnd);
939 static void remove_drift(int nset, int nbmin, int nbmax, real dt, enerdata_t *edat)
941 /* Remove the drift by performing a fit to y = ax+b.
942 Uses 5 iterations. */
946 edat->npoints = edat->nframes;
947 edat->nsteps = edat->nframes;
949 for (k = 0; (k < 5); k++)
951 for (i = 0; (i < nset); i++)
953 delta = edat->s[i].slope*dt;
957 fprintf(debug, "slope for set %d is %g\n", i, edat->s[i].slope);
960 for (j = 0; (j < edat->nframes); j++)
962 edat->s[i].ener[j] -= j*delta;
963 edat->s[i].es[j].sum = 0;
964 edat->s[i].es[j].sum2 = 0;
967 calc_averages(nset, edat, nbmin, nbmax);
971 static void calc_fluctuation_props(FILE *fp,
972 gmx_bool bDriftCorr, real dt,
974 char **leg, enerdata_t *edat,
975 int nbmin, int nbmax)
978 double vv, v, h, varv, hh, varh, tt, cv, cp, alpha, kappa, dcp, varet;
981 eVol, eEnth, eTemp, eEtot, eNR
983 const char *my_ener[] = { "Volume", "Enthalpy", "Temperature", "Total Energy" };
986 NANO3 = NANO*NANO*NANO;
989 fprintf(fp, "\nYou may want to use the -driftcorr flag in order to correct\n"
990 "for spurious drift in the graphs. Note that this is not\n"
991 "a substitute for proper equilibration and sampling!\n");
995 remove_drift(nset, nbmin, nbmax, dt, edat);
997 for (i = 0; (i < eNR); i++)
999 for (ii[i] = 0; (ii[i] < nset &&
1000 (gmx_strcasecmp(leg[ii[i]], my_ener[i]) != 0)); ii[i]++)
1004 /* if (ii[i] < nset)
1005 fprintf(fp,"Found %s data.\n",my_ener[i]);
1007 /* Compute it all! */
1008 alpha = kappa = cp = dcp = cv = NOTSET;
1012 if (ii[eTemp] < nset)
1014 tt = edat->s[ii[eTemp]].av;
1018 if ((ii[eVol] < nset) && (ii[eTemp] < nset))
1020 vv = edat->s[ii[eVol]].av*NANO3;
1021 varv = dsqr(edat->s[ii[eVol]].rmsd*NANO3);
1022 kappa = (varv/vv)/(BOLTZMANN*tt);
1026 if ((ii[eEnth] < nset) && (ii[eTemp] < nset))
1028 hh = KILO*edat->s[ii[eEnth]].av/AVOGADRO;
1029 varh = dsqr(KILO*edat->s[ii[eEnth]].rmsd/AVOGADRO);
1030 cp = AVOGADRO*((varh/nmol)/(BOLTZMANN*tt*tt));
1033 if ((ii[eEtot] < nset) && (hh == NOTSET) && (tt != NOTSET))
1035 /* Only compute cv in constant volume runs, which we can test
1036 by checking whether the enthalpy was computed.
1038 varet = sqr(edat->s[ii[eEtot]].rmsd);
1039 cv = KILO*((varet/nmol)/(BOLTZ*tt*tt));
1042 if ((ii[eVol] < nset) && (ii[eEnth] < nset) && (ii[eTemp] < nset))
1044 double v_sum, h_sum, vh_sum, v_aver, h_aver, vh_aver;
1045 vh_sum = v_sum = h_sum = 0;
1046 for (j = 0; (j < edat->nframes); j++)
1048 v = edat->s[ii[eVol]].ener[j]*NANO3;
1049 h = KILO*edat->s[ii[eEnth]].ener[j]/AVOGADRO;
1054 vh_aver = vh_sum / edat->nframes;
1055 v_aver = v_sum / edat->nframes;
1056 h_aver = h_sum / edat->nframes;
1057 alpha = (vh_aver-v_aver*h_aver)/(v_aver*BOLTZMANN*tt*tt);
1058 dcp = (v_aver*AVOGADRO/nmol)*tt*sqr(alpha)/(kappa);
1065 fprintf(fp, "\nWARNING: nmol = %d, this may not be what you want.\n",
1068 fprintf(fp, "\nTemperature dependent fluctuation properties at T = %g.\n", tt);
1069 fprintf(fp, "\nHeat capacities obtained from fluctuations do *not* include\n");
1070 fprintf(fp, "quantum corrections. If you want to get a more accurate estimate\n");
1071 fprintf(fp, "please use the g_dos program.\n\n");
1072 fprintf(fp, "WARNING: Please verify that your simulations are converged and perform\n"
1073 "a block-averaging error analysis (not implemented in g_energy yet)\n");
1079 fprintf(fp, "varv = %10g (m^6)\n", varv*AVOGADRO/nmol);
1084 fprintf(fp, "Volume = %10g m^3/mol\n",
1089 fprintf(fp, "Enthalpy = %10g kJ/mol\n",
1090 hh*AVOGADRO/(KILO*nmol));
1092 if (alpha != NOTSET)
1094 fprintf(fp, "Coefficient of Thermal Expansion Alpha_P = %10g (1/K)\n",
1097 if (kappa != NOTSET)
1099 fprintf(fp, "Isothermal Compressibility Kappa = %10g (J/m^3)\n",
1101 fprintf(fp, "Adiabatic bulk modulus = %10g (m^3/J)\n",
1106 fprintf(fp, "Heat capacity at constant pressure Cp = %10g J/mol K\n",
1111 fprintf(fp, "Heat capacity at constant volume Cv = %10g J/mol K\n",
1116 fprintf(fp, "Cp-Cv = %10g J/mol K\n",
1119 please_cite(fp, "Allen1987a");
1123 fprintf(fp, "You should select the temperature in order to obtain fluctuation properties.\n");
1127 static void analyse_ener(gmx_bool bCorr, const char *corrfn,
1128 gmx_bool bFee, gmx_bool bSum, gmx_bool bFluct,
1129 gmx_bool bVisco, const char *visfn, int nmol,
1130 gmx_int64_t start_step, double start_t,
1131 gmx_int64_t step, double t,
1134 int nset, int set[], gmx_bool *bIsEner,
1135 char **leg, gmx_enxnm_t *enm,
1136 real Vaver, real ezero,
1137 int nbmin, int nbmax,
1138 const output_env_t oenv)
1141 /* Check out the printed manual for equations! */
1142 double Dt, aver, stddev, errest, delta_t, totaldrift;
1143 enerdata_t *esum = NULL;
1144 real integral, intBulk, Temp = 0, Pres = 0;
1145 real pr_aver, pr_stddev, pr_errest;
1146 double beta = 0, expE, expEtot, *fee = NULL;
1148 int nexact, nnotexact;
1150 char buf[256], eebuf[100];
1152 nsteps = step - start_step + 1;
1155 fprintf(stdout, "Not enough steps (%s) for statistics\n",
1156 gmx_step_str(nsteps, buf));
1160 /* Calculate the time difference */
1161 delta_t = t - start_t;
1163 fprintf(stdout, "\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
1164 gmx_step_str(nsteps, buf), start_t, t, nset);
1166 calc_averages(nset, edat, nbmin, nbmax);
1170 esum = calc_sum(nset, edat, nbmin, nbmax);
1173 if (!edat->bHaveSums)
1182 for (i = 0; (i < nset); i++)
1184 if (edat->s[i].bExactStat)
1197 fprintf(stdout, "All statistics are over %s points\n",
1198 gmx_step_str(edat->npoints, buf));
1200 else if (nexact == 0 || edat->npoints == edat->nframes)
1202 fprintf(stdout, "All statistics are over %d points (frames)\n",
1207 fprintf(stdout, "The term%s", nnotexact == 1 ? "" : "s");
1208 for (i = 0; (i < nset); i++)
1210 if (!edat->s[i].bExactStat)
1212 fprintf(stdout, " '%s'", leg[i]);
1215 fprintf(stdout, " %s has statistics over %d points (frames)\n",
1216 nnotexact == 1 ? "is" : "are", edat->nframes);
1217 fprintf(stdout, "All other statistics are over %s points\n",
1218 gmx_step_str(edat->npoints, buf));
1220 fprintf(stdout, "\n");
1222 fprintf(stdout, "%-24s %10s %10s %10s %10s",
1223 "Energy", "Average", "Err.Est.", "RMSD", "Tot-Drift");
1226 fprintf(stdout, " %10s\n", "-kT ln<e^(E/kT)>");
1230 fprintf(stdout, "\n");
1232 fprintf(stdout, "-------------------------------------------------------------------------------\n");
1234 /* Initiate locals, only used with -sum */
1238 beta = 1.0/(BOLTZ*reftemp);
1241 for (i = 0; (i < nset); i++)
1243 aver = edat->s[i].av;
1244 stddev = edat->s[i].rmsd;
1245 errest = edat->s[i].ee;
1250 for (j = 0; (j < edat->nframes); j++)
1252 expE += std::exp(beta*(edat->s[i].ener[j] - aver)/nmol);
1256 expEtot += expE/edat->nframes;
1259 fee[i] = std::log(expE/edat->nframes)/beta + aver/nmol;
1261 if (std::strstr(leg[i], "empera") != NULL)
1265 else if (std::strstr(leg[i], "olum") != NULL)
1269 else if (std::strstr(leg[i], "essure") != NULL)
1275 pr_aver = aver/nmol-ezero;
1276 pr_stddev = stddev/nmol;
1277 pr_errest = errest/nmol;
1286 /* Multiply the slope in steps with the number of steps taken */
1287 totaldrift = (edat->nsteps - 1)*edat->s[i].slope;
1293 fprintf(stdout, "%-24s %10g %10s %10g %10g",
1294 leg[i], pr_aver, ee_pr(pr_errest, eebuf), pr_stddev, totaldrift);
1297 fprintf(stdout, " %10g", fee[i]);
1300 fprintf(stdout, " (%s)\n", enm[set[i]].unit);
1304 for (j = 0; (j < edat->nframes); j++)
1306 edat->s[i].ener[j] -= aver;
1312 totaldrift = (edat->nsteps - 1)*esum->s[0].slope;
1313 fprintf(stdout, "%-24s %10g %10s %10s %10g (%s)",
1314 "Total", esum->s[0].av/nmol, ee_pr(esum->s[0].ee/nmol, eebuf),
1315 "--", totaldrift/nmol, enm[set[0]].unit);
1316 /* pr_aver,pr_stddev,a,totaldrift */
1319 fprintf(stdout, " %10g %10g\n",
1320 std::log(expEtot)/beta + esum->s[0].av/nmol, std::log(expEtot)/beta);
1324 fprintf(stdout, "\n");
1328 /* Do correlation function */
1329 if (edat->nframes > 1)
1331 Dt = delta_t/(edat->nframes - 1);
1339 const char* leg[] = { "Shear", "Bulk" };
1344 /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
1346 /* Symmetrise tensor! (and store in first three elements)
1347 * And subtract average pressure!
1350 for (i = 0; i < 12; i++)
1352 snew(eneset[i], edat->nframes);
1354 for (i = 0; (i < edat->nframes); i++)
1356 eneset[0][i] = 0.5*(edat->s[1].ener[i]+edat->s[3].ener[i]);
1357 eneset[1][i] = 0.5*(edat->s[2].ener[i]+edat->s[6].ener[i]);
1358 eneset[2][i] = 0.5*(edat->s[5].ener[i]+edat->s[7].ener[i]);
1359 for (j = 3; j <= 11; j++)
1361 eneset[j][i] = edat->s[j].ener[i];
1363 eneset[11][i] -= Pres;
1366 /* Determine integrals of the off-diagonal pressure elements */
1368 for (i = 0; i < 3; i++)
1370 snew(eneint[i], edat->nframes + 1);
1375 for (i = 0; i < edat->nframes; i++)
1377 eneint[0][i+1] = eneint[0][i] + 0.5*(edat->s[1].es[i].sum + edat->s[3].es[i].sum)*Dt/edat->points[i];
1378 eneint[1][i+1] = eneint[1][i] + 0.5*(edat->s[2].es[i].sum + edat->s[6].es[i].sum)*Dt/edat->points[i];
1379 eneint[2][i+1] = eneint[2][i] + 0.5*(edat->s[5].es[i].sum + edat->s[7].es[i].sum)*Dt/edat->points[i];
1382 einstein_visco("evisco.xvg", "eviscoi.xvg",
1383 3, edat->nframes+1, eneint, Vaver, Temp, Dt, oenv);
1385 for (i = 0; i < 3; i++)
1391 /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
1392 /* Do it for shear viscosity */
1393 std::strcpy(buf, "Shear Viscosity");
1394 low_do_autocorr(corrfn, oenv, buf, edat->nframes, 3,
1395 (edat->nframes+1)/2, eneset, Dt,
1396 eacNormal, 1, TRUE, FALSE, FALSE, 0.0, 0.0, 0);
1398 /* Now for bulk viscosity */
1399 std::strcpy(buf, "Bulk Viscosity");
1400 low_do_autocorr(corrfn, oenv, buf, edat->nframes, 1,
1401 (edat->nframes+1)/2, &(eneset[11]), Dt,
1402 eacNormal, 1, TRUE, FALSE, FALSE, 0.0, 0.0, 0);
1404 factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
1405 fp = xvgropen(visfn, buf, "Time (ps)", "\\8h\\4 (cp)", oenv);
1406 xvgr_legend(fp, asize(leg), leg, oenv);
1408 /* Use trapezium rule for integration */
1411 nout = get_acfnout();
1412 if ((nout < 2) || (nout >= edat->nframes/2))
1414 nout = edat->nframes/2;
1416 for (i = 1; (i < nout); i++)
1418 integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
1419 intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
1420 fprintf(fp, "%10g %10g %10g\n", (i*Dt), integral, intBulk);
1424 for (i = 0; i < 12; i++)
1434 std::strcpy(buf, "Autocorrelation of Energy Fluctuations");
1438 std::strcpy(buf, "Energy Autocorrelation");
1441 do_autocorr(corrfn, oenv, buf, edat->nframes,
1443 bSum ? &edat->s[nset-1].ener : eneset,
1444 (delta_t/edat->nframes), eacNormal, FALSE);
1450 static void print_time(FILE *fp, double t)
1452 fprintf(fp, "%12.6f", t);
1455 static void print1(FILE *fp, gmx_bool bDp, real e)
1459 fprintf(fp, " %16.12f", e);
1463 fprintf(fp, " %10.6f", e);
1467 static void fec(const char *ene2fn, const char *runavgfn,
1468 real reftemp, int nset, int set[], char *leg[],
1469 enerdata_t *edat, double time[],
1470 const output_env_t oenv)
1472 const char * ravgleg[] = {
1473 "\\8D\\4E = E\\sB\\N-E\\sA\\N",
1474 "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N"
1478 int timecheck, nenergy, nenergy2, maxenergy;
1484 gmx_enxnm_t *enm = NULL;
1488 /* read second energy file */
1491 enx = open_enx(ene2fn, "r");
1492 do_enxnms(enx, &(fr->nre), &enm);
1494 snew(eneset2, nset+1);
1500 /* This loop searches for the first frame (when -b option is given),
1501 * or when this has been found it reads just one energy frame
1505 bCont = do_enx(enx, fr);
1509 timecheck = check_times(fr->t);
1513 while (bCont && (timecheck < 0));
1515 /* Store energies for analysis afterwards... */
1516 if ((timecheck == 0) && bCont)
1520 if (nenergy2 >= maxenergy)
1523 for (i = 0; i <= nset; i++)
1525 srenew(eneset2[i], maxenergy);
1528 GMX_RELEASE_ASSERT(time != NULL, "trying to dereference NULL time pointer");
1530 if (fr->t != time[nenergy2])
1532 fprintf(stderr, "\nWARNING time mismatch %g!=%g at frame %s\n",
1533 fr->t, time[nenergy2], gmx_step_str(fr->step, buf));
1535 for (i = 0; i < nset; i++)
1537 eneset2[i][nenergy2] = fr->ener[set[i]].e;
1543 while (bCont && (timecheck == 0));
1546 if (edat->nframes != nenergy2)
1548 fprintf(stderr, "\nWARNING file length mismatch %d!=%d\n",
1549 edat->nframes, nenergy2);
1551 nenergy = std::min(edat->nframes, nenergy2);
1553 /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
1557 fp = xvgropen(runavgfn, "Running average free energy difference",
1558 "Time (" unit_time ")", "\\8D\\4E (" unit_energy ")", oenv);
1559 xvgr_legend(fp, asize(ravgleg), ravgleg, oenv);
1561 fprintf(stdout, "\n%-24s %10s\n",
1562 "Energy", "dF = -kT ln < exp(-(EB-EA)/kT) >A");
1564 beta = 1.0/(BOLTZ*reftemp);
1565 for (i = 0; i < nset; i++)
1567 if (gmx_strcasecmp(leg[i], enm[set[i]].name) != 0)
1569 fprintf(stderr, "\nWARNING energy set name mismatch %s!=%s\n",
1570 leg[i], enm[set[i]].name);
1572 for (j = 0; j < nenergy; j++)
1574 dE = eneset2[i][j] - edat->s[i].ener[j];
1575 sum += std::exp(-dE*beta);
1578 fprintf(fp, "%10g %10g %10g\n",
1579 time[j], dE, -BOLTZ*reftemp*std::log(sum/(j+1)) );
1582 aver = -BOLTZ*reftemp*std::log(sum/nenergy);
1583 fprintf(stdout, "%-24s %10g\n", leg[i], aver);
1593 static void do_dhdl(t_enxframe *fr, t_inputrec *ir, FILE **fp_dhdl,
1594 const char *filename, gmx_bool bDp,
1595 int *blocks, int *hists, int *samples, int *nlambdas,
1596 const output_env_t oenv)
1598 const char *dhdl = "dH/d\\lambda", *deltag = "\\DeltaH", *lambda = "\\lambda";
1599 char title[STRLEN], label_x[STRLEN], label_y[STRLEN], legend[STRLEN];
1601 int nblock_hist = 0, nblock_dh = 0, nblock_dhcoll = 0;
1604 double temp = 0, start_time = 0, delta_time = 0, start_lambda = 0;
1605 static int setnr = 0;
1606 double *native_lambda_vec = NULL;
1607 const char **lambda_components = NULL;
1608 int n_lambda_vec = 0;
1610 /* now count the blocks & handle the global dh data */
1611 for (i = 0; i < fr->nblock; i++)
1613 if (fr->block[i].id == enxDHHIST)
1617 else if (fr->block[i].id == enxDH)
1621 else if (fr->block[i].id == enxDHCOLL)
1624 if ( (fr->block[i].nsub < 1) ||
1625 (fr->block[i].sub[0].type != xdr_datatype_double) ||
1626 (fr->block[i].sub[0].nr < 5))
1628 gmx_fatal(FARGS, "Unexpected block data");
1631 /* read the data from the DHCOLL block */
1632 temp = fr->block[i].sub[0].dval[0];
1633 start_time = fr->block[i].sub[0].dval[1];
1634 delta_time = fr->block[i].sub[0].dval[2];
1635 start_lambda = fr->block[i].sub[0].dval[3];
1636 if (fr->block[i].nsub > 1)
1638 if (n_lambda_vec == 0)
1640 n_lambda_vec = fr->block[i].sub[1].ival[1];
1644 if (n_lambda_vec != fr->block[i].sub[1].ival[1])
1647 "Unexpected change of basis set in lambda");
1650 if (lambda_components == NULL)
1652 snew(lambda_components, n_lambda_vec);
1654 if (native_lambda_vec == NULL)
1656 snew(native_lambda_vec, n_lambda_vec);
1658 for (j = 0; j < n_lambda_vec; j++)
1660 native_lambda_vec[j] = fr->block[i].sub[0].dval[5+j];
1661 lambda_components[j] =
1662 efpt_singular_names[fr->block[i].sub[1].ival[2+j]];
1668 if (nblock_hist == 0 && nblock_dh == 0)
1670 /* don't do anything */
1673 if (nblock_hist > 0 && nblock_dh > 0)
1675 gmx_fatal(FARGS, "This energy file contains both histogram dhdl data and non-histogram dhdl data. Don't know what to do.");
1681 /* we have standard, non-histogram data --
1682 call open_dhdl to open the file */
1683 /* TODO this is an ugly hack that needs to be fixed: this will only
1684 work if the order of data is always the same and if we're
1685 only using the g_energy compiled with the mdrun that produced
1687 *fp_dhdl = open_dhdl(filename, ir, oenv);
1691 sprintf(title, "N(%s)", deltag);
1692 sprintf(label_x, "%s (%s)", deltag, unit_energy);
1693 sprintf(label_y, "Samples");
1694 *fp_dhdl = xvgropen_type(filename, title, label_x, label_y, exvggtXNY, oenv);
1695 sprintf(buf, "T = %g (K), %s = %g", temp, lambda, start_lambda);
1696 xvgr_subtitle(*fp_dhdl, buf, oenv);
1700 (*hists) += nblock_hist;
1701 (*blocks) += nblock_dh;
1702 (*nlambdas) = nblock_hist+nblock_dh;
1704 /* write the data */
1705 if (nblock_hist > 0)
1707 gmx_int64_t sum = 0;
1709 for (i = 0; i < fr->nblock; i++)
1711 t_enxblock *blk = &(fr->block[i]);
1712 if (blk->id == enxDHHIST)
1714 double foreign_lambda, dx;
1716 int nhist, derivative;
1718 /* check the block types etc. */
1719 if ( (blk->nsub < 2) ||
1720 (blk->sub[0].type != xdr_datatype_double) ||
1721 (blk->sub[1].type != xdr_datatype_int64) ||
1722 (blk->sub[0].nr < 2) ||
1723 (blk->sub[1].nr < 2) )
1725 gmx_fatal(FARGS, "Unexpected block data in file");
1727 foreign_lambda = blk->sub[0].dval[0];
1728 dx = blk->sub[0].dval[1];
1729 nhist = blk->sub[1].lval[0];
1730 derivative = blk->sub[1].lval[1];
1731 for (j = 0; j < nhist; j++)
1734 x0 = blk->sub[1].lval[2+j];
1738 sprintf(legend, "N(%s(%s=%g) | %s=%g)",
1739 deltag, lambda, foreign_lambda,
1740 lambda, start_lambda);
1744 sprintf(legend, "N(%s | %s=%g)",
1745 dhdl, lambda, start_lambda);
1749 xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv);
1751 for (k = 0; k < blk->sub[j+2].nr; k++)
1756 hist = blk->sub[j+2].ival[k];
1759 fprintf(*fp_dhdl, "%g %d\n%g %d\n", xmin, hist,
1763 /* multiple histogram data blocks in one histogram
1764 mean that the second one is the reverse of the first one:
1765 for dhdl derivatives, it's important to know both the
1766 maximum and minimum values */
1771 (*samples) += static_cast<int>(sum/nblock_hist);
1778 for (i = 0; i < fr->nblock; i++)
1780 t_enxblock *blk = &(fr->block[i]);
1781 if (blk->id == enxDH)
1785 len = blk->sub[2].nr;
1789 if (len != blk->sub[2].nr)
1791 gmx_fatal(FARGS, "Length inconsistency in dhdl data");
1798 for (i = 0; i < len; i++)
1800 double time = start_time + delta_time*i;
1802 fprintf(*fp_dhdl, "%.4f ", time);
1804 for (j = 0; j < fr->nblock; j++)
1806 t_enxblock *blk = &(fr->block[j]);
1807 if (blk->id == enxDH)
1810 if (blk->sub[2].type == xdr_datatype_float)
1812 value = blk->sub[2].fval[i];
1816 value = blk->sub[2].dval[i];
1818 /* we need to decide which data type it is based on the count*/
1820 if (j == 1 && ir->bExpanded)
1822 fprintf(*fp_dhdl, "%4d", static_cast<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! */
1828 fprintf(*fp_dhdl, " %#.12g", value); /* print normal precision */
1832 fprintf(*fp_dhdl, " %#.8g", value); /* print normal precision */
1837 fprintf(*fp_dhdl, "\n");
1843 int gmx_energy(int argc, char *argv[])
1845 const char *desc[] = {
1846 "[THISMODULE] extracts energy components or distance restraint",
1847 "data from an energy file. The user is prompted to interactively",
1848 "select the desired energy terms.[PAR]",
1850 "Average, RMSD, and drift are calculated with full precision from the",
1851 "simulation (see printed manual). Drift is calculated by performing",
1852 "a least-squares fit of the data to a straight line. The reported total drift",
1853 "is the difference of the fit at the first and last point.",
1854 "An error estimate of the average is given based on a block averages",
1855 "over 5 blocks using the full-precision averages. The error estimate",
1856 "can be performed over multiple block lengths with the options",
1857 "[TT]-nbmin[tt] and [TT]-nbmax[tt].",
1858 "[BB]Note[bb] that in most cases the energy files contains averages over all",
1859 "MD steps, or over many more points than the number of frames in",
1860 "energy file. This makes the [THISMODULE] statistics output more accurate",
1861 "than the [REF].xvg[ref] output. When exact averages are not present in the energy",
1862 "file, the statistics mentioned above are simply over the single, per-frame",
1863 "energy values.[PAR]",
1865 "The term fluctuation gives the RMSD around the least-squares fit.[PAR]",
1867 "Some fluctuation-dependent properties can be calculated provided",
1868 "the correct energy terms are selected, and that the command line option",
1869 "[TT]-fluct_props[tt] is given. The following properties",
1870 "will be computed:",
1872 "=============================== ===================",
1873 "Property Energy terms needed",
1874 "=============================== ===================",
1875 "Heat capacity C[SUB]p[sub] (NPT sims): Enthalpy, Temp",
1876 "Heat capacity C[SUB]v[sub] (NVT sims): Etot, Temp",
1877 "Thermal expansion coeff. (NPT): Enthalpy, Vol, Temp",
1878 "Isothermal compressibility: Vol, Temp",
1879 "Adiabatic bulk modulus: Vol, Temp",
1880 "=============================== ===================",
1882 "You always need to set the number of molecules [TT]-nmol[tt].",
1883 "The C[SUB]p[sub]/C[SUB]v[sub] computations do [BB]not[bb] include any corrections",
1884 "for quantum effects. Use the [gmx-dos] program if you need that (and you do).[PAR]"
1885 "When the [TT]-viol[tt] option is set, the time averaged",
1886 "violations are plotted and the running time-averaged and",
1887 "instantaneous sum of violations are recalculated. Additionally",
1888 "running time-averaged and instantaneous distances between",
1889 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
1891 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
1892 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
1893 "The first two options plot the orientation, the last three the",
1894 "deviations of the orientations from the experimental values.",
1895 "The options that end on an 'a' plot the average over time",
1896 "as a function of restraint. The options that end on a 't'",
1897 "prompt the user for restraint label numbers and plot the data",
1898 "as a function of time. Option [TT]-odr[tt] plots the RMS",
1899 "deviation as a function of restraint.",
1900 "When the run used time or ensemble averaged orientation restraints,",
1901 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
1902 "not ensemble-averaged orientations and deviations instead of",
1903 "the time and ensemble averages.[PAR]",
1905 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
1906 "tensor for each orientation restraint experiment. With option",
1907 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
1909 "Option [TT]-odh[tt] extracts and plots the free energy data",
1910 "(Hamiltoian differences and/or the Hamiltonian derivative dhdl)",
1911 "from the [TT]ener.edr[tt] file.[PAR]",
1913 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
1914 "difference with an ideal gas state::",
1916 " [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]",
1917 " [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]",
1919 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
1920 "the average is over the ensemble (or time in a trajectory).",
1921 "Note that this is in principle",
1922 "only correct when averaging over the whole (Boltzmann) ensemble",
1923 "and using the potential energy. This also allows for an entropy",
1926 " [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",
1927 " [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",
1930 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
1931 "difference is calculated::",
1933 " dF = -kT [LN][CHEVRON][EXP]-(E[SUB]B[sub]-E[SUB]A[sub])/kT[exp][chevron][SUB]A[sub][ln] ,",
1935 "where E[SUB]A[sub] and E[SUB]B[sub] are the energies from the first and second energy",
1936 "files, and the average is over the ensemble A. The running average",
1937 "of the free energy difference is printed to a file specified by [TT]-ravg[tt].",
1938 "[BB]Note[bb] that the energies must both be calculated from the same trajectory."
1941 static gmx_bool bSum = FALSE, bFee = FALSE, bPrAll = FALSE, bFluct = FALSE, bDriftCorr = FALSE;
1942 static gmx_bool bDp = FALSE, bMutot = FALSE, bOrinst = FALSE, bOvec = FALSE, bFluctProps = FALSE;
1943 static int skip = 0, nmol = 1, nbmin = 5, nbmax = 5;
1944 static real reftemp = 300.0, ezero = 0;
1946 { "-fee", FALSE, etBOOL, {&bFee},
1947 "Do a free energy estimate" },
1948 { "-fetemp", FALSE, etREAL, {&reftemp},
1949 "Reference temperature for free energy calculation" },
1950 { "-zero", FALSE, etREAL, {&ezero},
1951 "Subtract a zero-point energy" },
1952 { "-sum", FALSE, etBOOL, {&bSum},
1953 "Sum the energy terms selected rather than display them all" },
1954 { "-dp", FALSE, etBOOL, {&bDp},
1955 "Print energies in high precision" },
1956 { "-nbmin", FALSE, etINT, {&nbmin},
1957 "Minimum number of blocks for error estimate" },
1958 { "-nbmax", FALSE, etINT, {&nbmax},
1959 "Maximum number of blocks for error estimate" },
1960 { "-mutot", FALSE, etBOOL, {&bMutot},
1961 "Compute the total dipole moment from the components" },
1962 { "-skip", FALSE, etINT, {&skip},
1963 "Skip number of frames between data points" },
1964 { "-aver", FALSE, etBOOL, {&bPrAll},
1965 "Also print the exact average and rmsd stored in the energy frames (only when 1 term is requested)" },
1966 { "-nmol", FALSE, etINT, {&nmol},
1967 "Number of molecules in your sample: the energies are divided by this number" },
1968 { "-fluct_props", FALSE, etBOOL, {&bFluctProps},
1969 "Compute properties based on energy fluctuations, like heat capacity" },
1970 { "-driftcorr", FALSE, etBOOL, {&bDriftCorr},
1971 "Useful only for calculations of fluctuation properties. The drift in the observables will be subtracted before computing the fluctuation properties."},
1972 { "-fluc", FALSE, etBOOL, {&bFluct},
1973 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
1974 { "-orinst", FALSE, etBOOL, {&bOrinst},
1975 "Analyse instantaneous orientation data" },
1976 { "-ovec", FALSE, etBOOL, {&bOvec},
1977 "Also plot the eigenvectors with [TT]-oten[tt]" }
1979 const char * drleg[] = {
1983 static const char *setnm[] = {
1984 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
1985 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
1986 "Volume", "Pressure"
1989 FILE *out = NULL, *fp_pairs = NULL, *fort = NULL, *fodt = NULL, *foten = NULL;
1990 FILE *fp_dhdl = NULL;
1994 gmx_localtop_t *top = NULL;
1997 gmx_enxnm_t *enm = NULL;
1998 t_enxframe *frame, *fr = NULL;
2000 #define NEXT (1-cur)
2001 int nre, teller, teller_disre, nfr;
2002 gmx_int64_t start_step;
2003 int nor = 0, nex = 0, norfr = 0, enx_i = 0;
2005 real *bounds = NULL, *violaver = NULL, *oobs = NULL, *orient = NULL, *odrms = NULL;
2006 int *index = NULL, *pair = NULL, norsel = 0, *orsel = NULL, *or_label = NULL;
2007 int nbounds = 0, npairs;
2008 gmx_bool bDisRe, bDRAll, bORA, bORT, bODA, bODR, bODT, bORIRE, bOTEN, bDHDL;
2009 gmx_bool bFoundStart, bCont, bVisco;
2010 double sum, sumaver, sumt, dbl;
2011 double *time = NULL;
2013 int *set = NULL, i, j, k, nset, sss;
2014 gmx_bool *bIsEner = NULL;
2015 char **pairleg, **odtleg, **otenleg;
2017 char *anm_j, *anm_k, *resnm_j, *resnm_k;
2018 int resnr_j, resnr_k;
2019 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
2022 t_enxblock *blk = NULL;
2023 t_enxblock *blk_disre = NULL;
2025 int dh_blocks = 0, dh_hists = 0, dh_samples = 0, dh_lambdas = 0;
2028 { efEDR, "-f", NULL, ffREAD },
2029 { efEDR, "-f2", NULL, ffOPTRD },
2030 { efTPR, "-s", NULL, ffOPTRD },
2031 { efXVG, "-o", "energy", ffWRITE },
2032 { efXVG, "-viol", "violaver", ffOPTWR },
2033 { efXVG, "-pairs", "pairs", ffOPTWR },
2034 { efXVG, "-ora", "orienta", ffOPTWR },
2035 { efXVG, "-ort", "orientt", ffOPTWR },
2036 { efXVG, "-oda", "orideva", ffOPTWR },
2037 { efXVG, "-odr", "oridevr", ffOPTWR },
2038 { efXVG, "-odt", "oridevt", ffOPTWR },
2039 { efXVG, "-oten", "oriten", ffOPTWR },
2040 { efXVG, "-corr", "enecorr", ffOPTWR },
2041 { efXVG, "-vis", "visco", ffOPTWR },
2042 { efXVG, "-ravg", "runavgdf", ffOPTWR },
2043 { efXVG, "-odh", "dhdl", ffOPTWR }
2045 #define NFILE asize(fnm)
2050 ppa = add_acf_pargs(&npargs, pa);
2051 if (!parse_common_args(&argc, argv,
2052 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END,
2053 NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv))
2058 bDRAll = opt2bSet("-pairs", NFILE, fnm);
2059 bDisRe = opt2bSet("-viol", NFILE, fnm) || bDRAll;
2060 bORA = opt2bSet("-ora", NFILE, fnm);
2061 bORT = opt2bSet("-ort", NFILE, fnm);
2062 bODA = opt2bSet("-oda", NFILE, fnm);
2063 bODR = opt2bSet("-odr", NFILE, fnm);
2064 bODT = opt2bSet("-odt", NFILE, fnm);
2065 bORIRE = bORA || bORT || bODA || bODR || bODT;
2066 bOTEN = opt2bSet("-oten", NFILE, fnm);
2067 bDHDL = opt2bSet("-odh", NFILE, fnm);
2072 fp = open_enx(ftp2fn(efEDR, NFILE, fnm), "r");
2073 do_enxnms(fp, &nre, &enm);
2077 bVisco = opt2bSet("-vis", NFILE, fnm);
2079 if ((!bDisRe) && (!bDHDL))
2083 nset = asize(setnm);
2085 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
2086 for (j = 0; j < nset; j++)
2088 for (i = 0; i < nre; i++)
2090 if (std::strstr(enm[i].name, setnm[j]))
2098 if (gmx_strcasecmp(setnm[j], "Volume") == 0)
2100 printf("Enter the box volume (" unit_volume "): ");
2101 if (1 != scanf("%lf", &dbl))
2103 gmx_fatal(FARGS, "Error reading user input");
2109 gmx_fatal(FARGS, "Could not find term %s for viscosity calculation",
2117 set = select_by_name(nre, enm, &nset);
2119 /* Print all the different units once */
2120 sprintf(buf, "(%s)", enm[set[0]].unit);
2121 for (i = 1; i < nset; i++)
2123 for (j = 0; j < i; j++)
2125 if (std::strcmp(enm[set[i]].unit, enm[set[j]].unit) == 0)
2132 std::strcat(buf, ", (");
2133 std::strcat(buf, enm[set[i]].unit);
2134 std::strcat(buf, ")");
2137 out = xvgropen(opt2fn("-o", NFILE, fnm), "GROMACS Energies", "Time (ps)", buf,
2141 for (i = 0; (i < nset); i++)
2143 leg[i] = enm[set[i]].name;
2147 leg[nset] = gmx_strdup("Sum");
2148 xvgr_legend(out, nset+1, (const char**)leg, oenv);
2152 xvgr_legend(out, nset, (const char**)leg, oenv);
2155 snew(bIsEner, nset);
2156 for (i = 0; (i < nset); i++)
2159 for (j = 0; (j <= F_ETOT); j++)
2161 bIsEner[i] = bIsEner[i] ||
2162 (gmx_strcasecmp(interaction_function[j].longname, leg[i]) == 0);
2166 if (bPrAll && nset > 1)
2168 gmx_fatal(FARGS, "Printing averages can only be done when a single set is selected");
2173 if (bORIRE || bOTEN)
2175 get_orires_parms(ftp2fn(efTPR, NFILE, fnm), &nor, &nex, &or_label, &oobs);
2199 fprintf(stderr, "Select the orientation restraint labels you want (-1 is all)\n");
2200 fprintf(stderr, "End your selection with 0\n");
2207 if (1 != scanf("%d", &(orsel[j])))
2209 gmx_fatal(FARGS, "Error reading user input");
2212 while (orsel[j] > 0);
2215 fprintf(stderr, "Selecting all %d orientation restraints\n", nor);
2218 for (i = 0; i < nor; i++)
2225 /* Build the selection */
2227 for (i = 0; i < j; i++)
2229 for (k = 0; k < nor; k++)
2231 if (or_label[k] == orsel[i])
2240 fprintf(stderr, "Orientation restraint label %d not found\n",
2245 snew(odtleg, norsel);
2246 for (i = 0; i < norsel; i++)
2248 snew(odtleg[i], 256);
2249 sprintf(odtleg[i], "%d", or_label[orsel[i]]);
2253 fort = xvgropen(opt2fn("-ort", NFILE, fnm), "Calculated orientations",
2254 "Time (ps)", "", oenv);
2255 if (bOrinst && output_env_get_print_xvgr_codes(oenv))
2257 fprintf(fort, "%s", orinst_sub);
2259 xvgr_legend(fort, norsel, (const char**)odtleg, oenv);
2263 fodt = xvgropen(opt2fn("-odt", NFILE, fnm),
2264 "Orientation restraint deviation",
2265 "Time (ps)", "", oenv);
2266 if (bOrinst && output_env_get_print_xvgr_codes(oenv))
2268 fprintf(fodt, "%s", orinst_sub);
2270 xvgr_legend(fodt, norsel, (const char**)odtleg, oenv);
2276 foten = xvgropen(opt2fn("-oten", NFILE, fnm),
2277 "Order tensor", "Time (ps)", "", oenv);
2278 snew(otenleg, bOvec ? nex*12 : nex*3);
2279 for (i = 0; i < nex; i++)
2281 for (j = 0; j < 3; j++)
2283 sprintf(buf, "eig%d", j+1);
2284 otenleg[(bOvec ? 12 : 3)*i+j] = gmx_strdup(buf);
2288 for (j = 0; j < 9; j++)
2290 sprintf(buf, "vec%d%s", j/3+1, j%3 == 0 ? "x" : (j%3 == 1 ? "y" : "z"));
2291 otenleg[12*i+3+j] = gmx_strdup(buf);
2295 xvgr_legend(foten, bOvec ? nex*12 : nex*3, (const char**)otenleg, oenv);
2300 nbounds = get_bounds(ftp2fn(efTPR, NFILE, fnm), &bounds, &index, &pair, &npairs,
2302 snew(violaver, npairs);
2303 out = xvgropen(opt2fn("-o", NFILE, fnm), "Sum of Violations",
2304 "Time (ps)", "nm", oenv);
2305 xvgr_legend(out, 2, drleg, oenv);
2308 fp_pairs = xvgropen(opt2fn("-pairs", NFILE, fnm), "Pair Distances",
2309 "Time (ps)", "Distance (nm)", oenv);
2310 if (output_env_get_print_xvgr_codes(oenv))
2312 fprintf(fp_pairs, "@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
2319 get_dhdl_parms(ftp2fn(efTPR, NFILE, fnm), &ir);
2322 /* Initiate energies and set them to zero */
2329 edat.bHaveSums = TRUE;
2332 /* Initiate counters */
2335 bFoundStart = FALSE;
2340 /* This loop searches for the first frame (when -b option is given),
2341 * or when this has been found it reads just one energy frame
2345 bCont = do_enx(fp, &(frame[NEXT]));
2348 timecheck = check_times(frame[NEXT].t);
2351 while (bCont && (timecheck < 0));
2353 if ((timecheck == 0) && bCont)
2355 /* We read a valid frame, so we can use it */
2356 fr = &(frame[NEXT]);
2360 /* The frame contains energies, so update cur */
2363 if (edat.nframes % 1000 == 0)
2365 srenew(edat.step, edat.nframes+1000);
2366 std::memset(&(edat.step[edat.nframes]), 0, 1000*sizeof(edat.step[0]));
2367 srenew(edat.steps, edat.nframes+1000);
2368 std::memset(&(edat.steps[edat.nframes]), 0, 1000*sizeof(edat.steps[0]));
2369 srenew(edat.points, edat.nframes+1000);
2370 std::memset(&(edat.points[edat.nframes]), 0, 1000*sizeof(edat.points[0]));
2372 for (i = 0; i < nset; i++)
2374 srenew(edat.s[i].ener, edat.nframes+1000);
2375 std::memset(&(edat.s[i].ener[edat.nframes]), 0,
2376 1000*sizeof(edat.s[i].ener[0]));
2377 srenew(edat.s[i].es, edat.nframes+1000);
2378 std::memset(&(edat.s[i].es[edat.nframes]), 0,
2379 1000*sizeof(edat.s[i].es[0]));
2384 edat.step[nfr] = fr->step;
2389 /* Initiate the previous step data */
2390 start_step = fr->step;
2392 /* Initiate the energy sums */
2393 edat.steps[nfr] = 1;
2394 edat.points[nfr] = 1;
2395 for (i = 0; i < nset; i++)
2398 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2399 edat.s[i].es[nfr].sum2 = 0;
2406 edat.steps[nfr] = fr->nsteps;
2410 /* mdrun only calculated the energy at energy output
2411 * steps. We don't need to check step intervals.
2413 edat.points[nfr] = 1;
2414 for (i = 0; i < nset; i++)
2417 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2418 edat.s[i].es[nfr].sum2 = 0;
2421 edat.bHaveSums = FALSE;
2423 else if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
2425 /* We have statistics to the previous frame */
2426 edat.points[nfr] = fr->nsum;
2427 for (i = 0; i < nset; i++)
2430 edat.s[i].es[nfr].sum = fr->ener[sss].esum;
2431 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
2433 edat.npoints += fr->nsum;
2437 /* The interval does not match fr->nsteps:
2438 * can not do exact averages.
2440 edat.bHaveSums = FALSE;
2443 edat.nsteps = fr->step - start_step + 1;
2445 for (i = 0; i < nset; i++)
2447 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
2451 * Define distance restraint legends. Can only be done after
2452 * the first frame has been read... (Then we know how many there are)
2454 blk_disre = find_block_id_enxframe(fr, enxDISRE, NULL);
2455 if (bDisRe && bDRAll && !leg && blk_disre)
2460 fa = top->idef.il[F_DISRES].iatoms;
2461 ip = top->idef.iparams;
2462 if (blk_disre->nsub != 2 ||
2463 (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
2465 gmx_incons("Number of disre sub-blocks not equal to 2");
2468 ndisre = blk_disre->sub[0].nr;
2469 if (ndisre != top->idef.il[F_DISRES].nr/3)
2471 gmx_fatal(FARGS, "Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
2472 ndisre, top->idef.il[F_DISRES].nr/3);
2474 snew(pairleg, ndisre);
2475 for (i = 0; i < ndisre; i++)
2477 snew(pairleg[i], 30);
2480 gmx_mtop_atominfo_global(&mtop, j, &anm_j, &resnr_j, &resnm_j);
2481 gmx_mtop_atominfo_global(&mtop, k, &anm_k, &resnr_k, &resnm_k);
2482 sprintf(pairleg[i], "%d %s %d %s (%d)",
2483 resnr_j, anm_j, resnr_k, anm_k,
2484 ip[fa[3*i]].disres.label);
2486 set = select_it(ndisre, pairleg, &nset);
2488 for (i = 0; (i < nset); i++)
2491 sprintf(leg[2*i], "a %s", pairleg[set[i]]);
2492 snew(leg[2*i+1], 32);
2493 sprintf(leg[2*i+1], "i %s", pairleg[set[i]]);
2495 xvgr_legend(fp_pairs, 2*nset, (const char**)leg, oenv);
2499 * Store energies for analysis afterwards...
2501 if (!bDisRe && !bDHDL && (fr->nre > 0))
2503 if (edat.nframes % 1000 == 0)
2505 srenew(time, edat.nframes+1000);
2507 time[edat.nframes] = fr->t;
2511 * Printing time, only when we do not want to skip frames
2513 if (!skip || teller % skip == 0)
2517 /*******************************************
2518 * D I S T A N C E R E S T R A I N T S
2519 *******************************************/
2522 GMX_RELEASE_ASSERT(blk_disre != NULL, "Trying to dereference NULL blk_disre pointer");
2524 float *disre_rt = blk_disre->sub[0].fval;
2525 float *disre_rm3tav = blk_disre->sub[1].fval;
2527 double *disre_rt = blk_disre->sub[0].dval;
2528 double *disre_rm3tav = blk_disre->sub[1].dval;
2531 print_time(out, fr->t);
2532 if (violaver == NULL)
2534 snew(violaver, ndisre);
2537 /* Subtract bounds from distances, to calculate violations */
2538 calc_violations(disre_rt, disre_rm3tav,
2539 nbounds, pair, bounds, violaver, &sumt, &sumaver);
2541 fprintf(out, " %8.4f %8.4f\n", sumaver, sumt);
2544 print_time(fp_pairs, fr->t);
2545 for (i = 0; (i < nset); i++)
2548 fprintf(fp_pairs, " %8.4f", mypow(disre_rm3tav[sss], minthird));
2549 fprintf(fp_pairs, " %8.4f", disre_rt[sss]);
2551 fprintf(fp_pairs, "\n");
2558 do_dhdl(fr, &ir, &fp_dhdl, opt2fn("-odh", NFILE, fnm), bDp, &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas, oenv);
2561 /*******************************************
2563 *******************************************/
2570 /* We skip frames with single points (usually only the first frame),
2571 * since they would result in an average plot with outliers.
2575 print_time(out, fr->t);
2576 print1(out, bDp, fr->ener[set[0]].e);
2577 print1(out, bDp, fr->ener[set[0]].esum/fr->nsum);
2578 print1(out, bDp, std::sqrt(fr->ener[set[0]].eav/fr->nsum));
2584 print_time(out, fr->t);
2588 for (i = 0; i < nset; i++)
2590 sum += fr->ener[set[i]].e;
2592 print1(out, bDp, sum/nmol-ezero);
2596 for (i = 0; (i < nset); i++)
2600 print1(out, bDp, (fr->ener[set[i]].e)/nmol-ezero);
2604 print1(out, bDp, fr->ener[set[i]].e);
2611 blk = find_block_id_enxframe(fr, enx_i, NULL);
2615 xdr_datatype dt = xdr_datatype_float;
2617 xdr_datatype dt = xdr_datatype_double;
2621 if ( (blk->nsub != 1) || (blk->sub[0].type != dt) )
2623 gmx_fatal(FARGS, "Orientational restraints read in incorrectly");
2626 vals = blk->sub[0].fval;
2628 vals = blk->sub[0].dval;
2631 if (blk->sub[0].nr != nor)
2633 gmx_fatal(FARGS, "Number of orientation restraints in energy file (%d) does not match with the topology (%d)", blk->sub[0].nr);
2637 for (i = 0; i < nor; i++)
2639 orient[i] += vals[i];
2644 for (i = 0; i < nor; i++)
2646 odrms[i] += sqr(vals[i]-oobs[i]);
2651 fprintf(fort, " %10f", fr->t);
2652 for (i = 0; i < norsel; i++)
2654 fprintf(fort, " %g", vals[orsel[i]]);
2656 fprintf(fort, "\n");
2660 fprintf(fodt, " %10f", fr->t);
2661 for (i = 0; i < norsel; i++)
2663 fprintf(fodt, " %g", vals[orsel[i]]-oobs[orsel[i]]);
2665 fprintf(fodt, "\n");
2669 blk = find_block_id_enxframe(fr, enxORT, NULL);
2673 xdr_datatype dt = xdr_datatype_float;
2675 xdr_datatype dt = xdr_datatype_double;
2679 if ( (blk->nsub != 1) || (blk->sub[0].type != dt) )
2681 gmx_fatal(FARGS, "Orientational restraints read in incorrectly");
2684 vals = blk->sub[0].fval;
2686 vals = blk->sub[0].dval;
2689 if (blk->sub[0].nr != nex*12)
2691 gmx_fatal(FARGS, "Number of orientation experiments in energy file (%g) does not match with the topology (%d)",
2692 blk->sub[0].nr/12, nex);
2694 fprintf(foten, " %10f", fr->t);
2695 for (i = 0; i < nex; i++)
2697 for (j = 0; j < (bOvec ? 12 : 3); j++)
2699 fprintf(foten, " %g", vals[i*12+j]);
2702 fprintf(foten, "\n");
2709 while (bCont && (timecheck == 0));
2711 fprintf(stderr, "\n");
2720 xvgrclose(fp_pairs);
2733 out = xvgropen(opt2fn("-ora", NFILE, fnm),
2734 "Average calculated orientations",
2735 "Restraint label", "", oenv);
2736 if (bOrinst && output_env_get_print_xvgr_codes(oenv))
2738 fprintf(out, "%s", orinst_sub);
2740 for (i = 0; i < nor; i++)
2742 fprintf(out, "%5d %g\n", or_label[i], orient[i]/norfr);
2748 out = xvgropen(opt2fn("-oda", NFILE, fnm),
2749 "Average restraint deviation",
2750 "Restraint label", "", oenv);
2751 if (bOrinst && output_env_get_print_xvgr_codes(oenv))
2753 fprintf(out, "%s", orinst_sub);
2755 for (i = 0; i < nor; i++)
2757 fprintf(out, "%5d %g\n", or_label[i], orient[i]/norfr-oobs[i]);
2763 out = xvgropen(opt2fn("-odr", NFILE, fnm),
2764 "RMS orientation restraint deviations",
2765 "Restraint label", "", oenv);
2766 if (bOrinst && output_env_get_print_xvgr_codes(oenv))
2768 fprintf(out, "%s", orinst_sub);
2770 for (i = 0; i < nor; i++)
2772 fprintf(out, "%5d %g\n", or_label[i], std::sqrt(odrms[i]/norfr));
2783 analyse_disre(opt2fn("-viol", NFILE, fnm),
2784 teller_disre, violaver, bounds, index, pair, nbounds, oenv);
2790 gmx_fio_fclose(fp_dhdl);
2791 printf("\n\nWrote %d lambda values with %d samples as ",
2792 dh_lambdas, dh_samples);
2795 printf("%d dH histograms ", dh_hists);
2799 printf("%d dH data blocks ", dh_blocks);
2801 printf("to %s\n", opt2fn("-odh", NFILE, fnm));
2806 gmx_fatal(FARGS, "No dH data in %s\n", opt2fn("-f", NFILE, fnm));
2812 double dt = (frame[cur].t-start_t)/(edat.nframes-1);
2813 analyse_ener(opt2bSet("-corr", NFILE, fnm), opt2fn("-corr", NFILE, fnm),
2814 bFee, bSum, opt2parg_bSet("-nmol", npargs, ppa),
2815 bVisco, opt2fn("-vis", NFILE, fnm),
2817 start_step, start_t, frame[cur].step, frame[cur].t,
2819 nset, set, bIsEner, leg, enm, Vaver, ezero, nbmin, nbmax,
2823 calc_fluctuation_props(stdout, bDriftCorr, dt, nset, nmol, leg, &edat,
2827 if (opt2bSet("-f2", NFILE, fnm))
2829 fec(opt2fn("-f2", NFILE, fnm), opt2fn("-ravg", NFILE, fnm),
2830 reftemp, nset, set, leg, &edat, time, oenv);
2834 const char *nxy = "-nxy";
2836 do_view(oenv, opt2fn("-o", NFILE, fnm), nxy);
2837 do_view(oenv, opt2fn_null("-ravg", NFILE, fnm), nxy);
2838 do_view(oenv, opt2fn_null("-ora", NFILE, fnm), nxy);
2839 do_view(oenv, opt2fn_null("-ort", NFILE, fnm), nxy);
2840 do_view(oenv, opt2fn_null("-oda", NFILE, fnm), nxy);
2841 do_view(oenv, opt2fn_null("-odr", NFILE, fnm), nxy);
2842 do_view(oenv, opt2fn_null("-odt", NFILE, fnm), nxy);
2843 do_view(oenv, opt2fn_null("-oten", NFILE, fnm), nxy);
2844 do_view(oenv, opt2fn_null("-odh", NFILE, fnm), nxy);