Remove continuation from convert_tpr
[gromacs.git] / src / gromacs / gmxana / gmx_energy.cpp
blob97d2be8a7176f0ca13c5bce484f28970689b4f3e
1 /*
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,2016, 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.
37 #include "gmxpre.h"
39 #include <cmath>
40 #include <cstdlib>
41 #include <cstring>
43 #include <algorithm>
45 #include "gromacs/commandline/pargs.h"
46 #include "gromacs/commandline/viewit.h"
47 #include "gromacs/correlationfunctions/autocorr.h"
48 #include "gromacs/fileio/enxio.h"
49 #include "gromacs/fileio/gmxfio.h"
50 #include "gromacs/fileio/tpxio.h"
51 #include "gromacs/fileio/trxio.h"
52 #include "gromacs/fileio/xvgr.h"
53 #include "gromacs/gmxana/gmx_ana.h"
54 #include "gromacs/gmxana/gstat.h"
55 #include "gromacs/math/functions.h"
56 #include "gromacs/math/units.h"
57 #include "gromacs/math/vec.h"
58 #include "gromacs/mdlib/mdebin.h"
59 #include "gromacs/mdtypes/inputrec.h"
60 #include "gromacs/mdtypes/md_enums.h"
61 #include "gromacs/topology/ifunc.h"
62 #include "gromacs/topology/mtop_util.h"
63 #include "gromacs/topology/topology.h"
64 #include "gromacs/utility/arraysize.h"
65 #include "gromacs/utility/cstringutil.h"
66 #include "gromacs/utility/fatalerror.h"
67 #include "gromacs/utility/gmxassert.h"
68 #include "gromacs/utility/pleasecite.h"
69 #include "gromacs/utility/smalloc.h"
71 static real minthird = -1.0/3.0, minsixth = -1.0/6.0;
72 static const int NOTSET = -23451;
74 typedef struct {
75 real sum;
76 real sum2;
77 } exactsum_t;
79 typedef struct {
80 real *ener;
81 exactsum_t *es;
82 gmx_bool bExactStat;
83 double av;
84 double rmsd;
85 double ee;
86 double slope;
87 } enerdat_t;
89 typedef struct {
90 gmx_int64_t nsteps;
91 gmx_int64_t npoints;
92 int nframes;
93 int *step;
94 int *steps;
95 int *points;
96 enerdat_t *s;
97 gmx_bool bHaveSums;
98 } enerdata_t;
100 static double mypow(double x, double y)
102 if (x > 0)
104 return std::pow(x, y);
106 else
108 return 0.0;
112 static int *select_it(int nre, char *nm[], int *nset)
114 gmx_bool *bE;
115 int n, k, j, i;
116 int *set;
117 gmx_bool bVerbose = TRUE;
119 if ((getenv("GMX_ENER_VERBOSE")) != NULL)
121 bVerbose = FALSE;
124 fprintf(stderr, "Select the terms you want from the following list\n");
125 fprintf(stderr, "End your selection with 0\n");
127 if (bVerbose)
129 for (k = 0; (k < nre); )
131 for (j = 0; (j < 4) && (k < nre); j++, k++)
133 fprintf(stderr, " %3d=%14s", k+1, nm[k]);
135 fprintf(stderr, "\n");
139 snew(bE, nre);
142 if (1 != scanf("%d", &n))
144 gmx_fatal(FARGS, "Error reading user input");
146 if ((n > 0) && (n <= nre))
148 bE[n-1] = TRUE;
151 while (n != 0);
153 snew(set, nre);
154 for (i = (*nset) = 0; (i < nre); i++)
156 if (bE[i])
158 set[(*nset)++] = i;
162 sfree(bE);
164 return set;
167 static void chomp(char *buf)
169 int len = std::strlen(buf);
171 while ((len > 0) && (buf[len-1] == '\n'))
173 buf[len-1] = '\0';
174 len--;
178 static int *select_by_name(int nre, gmx_enxnm_t *nm, int *nset)
180 gmx_bool *bE;
181 int k, kk, j, i, nmatch, nind, nss;
182 int *set;
183 gmx_bool bEOF, bVerbose = TRUE, bLong = FALSE;
184 char *ptr, buf[STRLEN];
185 const char *fm4 = "%3d %-14s";
186 const char *fm2 = "%3d %-34s";
187 char **newnm = NULL;
189 if ((getenv("GMX_ENER_VERBOSE")) != NULL)
191 bVerbose = FALSE;
194 fprintf(stderr, "\n");
195 fprintf(stderr, "Select the terms you want from the following list by\n");
196 fprintf(stderr, "selecting either (part of) the name or the number or a combination.\n");
197 fprintf(stderr, "End your selection with an empty line or a zero.\n");
198 fprintf(stderr, "-------------------------------------------------------------------\n");
200 snew(newnm, nre);
201 j = 0;
202 for (k = 0; k < nre; k++)
204 newnm[k] = gmx_strdup(nm[k].name);
205 /* Insert dashes in all the names */
206 while ((ptr = std::strchr(newnm[k], ' ')) != NULL)
208 *ptr = '-';
210 if (bVerbose)
212 if (j == 0)
214 if (k > 0)
216 fprintf(stderr, "\n");
218 bLong = FALSE;
219 for (kk = k; kk < k+4; kk++)
221 if (kk < nre && std::strlen(nm[kk].name) > 14)
223 bLong = TRUE;
227 else
229 fprintf(stderr, " ");
231 if (!bLong)
233 fprintf(stderr, fm4, k+1, newnm[k]);
234 j++;
235 if (j == 4)
237 j = 0;
240 else
242 fprintf(stderr, fm2, k+1, newnm[k]);
243 j++;
244 if (j == 2)
246 j = 0;
251 if (bVerbose)
253 fprintf(stderr, "\n\n");
256 snew(bE, nre);
258 bEOF = FALSE;
259 while (!bEOF && (fgets2(buf, STRLEN-1, stdin)))
261 /* Remove newlines */
262 chomp(buf);
264 /* Remove spaces */
265 trim(buf);
267 /* Empty line means end of input */
268 bEOF = (std::strlen(buf) == 0);
269 if (!bEOF)
271 ptr = buf;
274 if (!bEOF)
276 /* First try to read an integer */
277 nss = sscanf(ptr, "%d", &nind);
278 if (nss == 1)
280 /* Zero means end of input */
281 if (nind == 0)
283 bEOF = TRUE;
285 else if ((1 <= nind) && (nind <= nre))
287 bE[nind-1] = TRUE;
289 else
291 fprintf(stderr, "number %d is out of range\n", nind);
294 else
296 /* Now try to read a string */
297 nmatch = 0;
298 for (nind = 0; nind < nre; nind++)
300 if (gmx_strcasecmp(newnm[nind], ptr) == 0)
302 bE[nind] = TRUE;
303 nmatch++;
306 if (nmatch == 0)
308 i = std::strlen(ptr);
309 nmatch = 0;
310 for (nind = 0; nind < nre; nind++)
312 if (gmx_strncasecmp(newnm[nind], ptr, i) == 0)
314 bE[nind] = TRUE;
315 nmatch++;
318 if (nmatch == 0)
320 fprintf(stderr, "String '%s' does not match anything\n", ptr);
325 /* Look for the first space, and remove spaces from there */
326 if ((ptr = std::strchr(ptr, ' ')) != NULL)
328 trim(ptr);
331 while (!bEOF && (ptr && (std::strlen(ptr) > 0)));
335 snew(set, nre);
336 for (i = (*nset) = 0; (i < nre); i++)
338 if (bE[i])
340 set[(*nset)++] = i;
344 sfree(bE);
346 if (*nset == 0)
348 gmx_fatal(FARGS, "No energy terms selected");
351 for (i = 0; (i < nre); i++)
353 sfree(newnm[i]);
355 sfree(newnm);
357 return set;
360 static void get_dhdl_parms(const char *topnm, t_inputrec *ir)
362 gmx_mtop_t mtop;
363 int natoms;
364 matrix box;
366 /* all we need is the ir to be able to write the label */
367 read_tpx(topnm, ir, box, &natoms, NULL, NULL, &mtop);
370 static void get_orires_parms(const char *topnm,
371 int *nor, int *nex, int **label, real **obs)
373 gmx_mtop_t mtop;
374 gmx_localtop_t *top;
375 t_inputrec ir;
376 t_iparams *ip;
377 int natoms, i;
378 t_iatom *iatom;
379 int nb;
380 matrix box;
382 read_tpx(topnm, &ir, box, &natoms, NULL, NULL, &mtop);
383 top = gmx_mtop_generate_local_top(&mtop, ir.efep != efepNO);
385 ip = top->idef.iparams;
386 iatom = top->idef.il[F_ORIRES].iatoms;
388 /* Count how many distance restraint there are... */
389 nb = top->idef.il[F_ORIRES].nr;
390 if (nb == 0)
392 gmx_fatal(FARGS, "No orientation restraints in topology!\n");
395 *nor = nb/3;
396 *nex = 0;
397 snew(*label, *nor);
398 snew(*obs, *nor);
399 for (i = 0; i < nb; i += 3)
401 (*label)[i/3] = ip[iatom[i]].orires.label;
402 (*obs)[i/3] = ip[iatom[i]].orires.obs;
403 if (ip[iatom[i]].orires.ex >= *nex)
405 *nex = ip[iatom[i]].orires.ex+1;
408 fprintf(stderr, "Found %d orientation restraints with %d experiments",
409 *nor, *nex);
412 static int get_bounds(const char *topnm,
413 real **bounds, int **index, int **dr_pair, int *npairs,
414 gmx_mtop_t *mtop, gmx_localtop_t **ltop, t_inputrec *ir)
416 gmx_localtop_t *top;
417 t_functype *functype;
418 t_iparams *ip;
419 int natoms, i, j, k, type, ftype, natom;
420 t_ilist *disres;
421 t_iatom *iatom;
422 real *b;
423 int *ind, *pair;
424 int nb, label1;
425 matrix box;
427 read_tpx(topnm, ir, box, &natoms, NULL, NULL, mtop);
428 snew(*ltop, 1);
429 top = gmx_mtop_generate_local_top(mtop, ir->efep != efepNO);
430 *ltop = top;
432 functype = top->idef.functype;
433 ip = top->idef.iparams;
435 /* Count how many distance restraint there are... */
436 nb = top->idef.il[F_DISRES].nr;
437 if (nb == 0)
439 gmx_fatal(FARGS, "No distance restraints in topology!\n");
442 /* Allocate memory */
443 snew(b, nb);
444 snew(ind, nb);
445 snew(pair, nb+1);
447 /* Fill the bound array */
448 nb = 0;
449 for (i = 0; (i < top->idef.ntypes); i++)
451 ftype = functype[i];
452 if (ftype == F_DISRES)
455 label1 = ip[i].disres.label;
456 b[nb] = ip[i].disres.up1;
457 ind[nb] = label1;
458 nb++;
461 *bounds = b;
463 /* Fill the index array */
464 label1 = -1;
465 disres = &(top->idef.il[F_DISRES]);
466 iatom = disres->iatoms;
467 for (i = j = k = 0; (i < disres->nr); )
469 type = iatom[i];
470 ftype = top->idef.functype[type];
471 natom = interaction_function[ftype].nratoms+1;
472 if (label1 != top->idef.iparams[type].disres.label)
474 pair[j] = k;
475 label1 = top->idef.iparams[type].disres.label;
476 j++;
478 k++;
479 i += natom;
481 pair[j] = k;
482 *npairs = k;
483 if (j != nb)
485 gmx_incons("get_bounds for distance restraints");
488 *index = ind;
489 *dr_pair = pair;
491 return nb;
494 static void calc_violations(real rt[], real rav3[], int nb, int index[],
495 real bounds[], real *viol, double *st, double *sa)
497 const real sixth = 1.0/6.0;
498 int i, j;
499 double rsum, rav, sumaver, sumt;
501 sumaver = 0;
502 sumt = 0;
503 for (i = 0; (i < nb); i++)
505 rsum = 0.0;
506 rav = 0.0;
507 for (j = index[i]; (j < index[i+1]); j++)
509 if (viol)
511 viol[j] += mypow(rt[j], -3.0);
513 rav += gmx::square(rav3[j]);
514 rsum += mypow(rt[j], -6);
516 rsum = std::max(0.0, mypow(rsum, -sixth)-bounds[i]);
517 rav = std::max(0.0, mypow(rav, -sixth)-bounds[i]);
519 sumt += rsum;
520 sumaver += rav;
522 *st = sumt;
523 *sa = sumaver;
526 static void analyse_disre(const char *voutfn, int nframes,
527 real violaver[], real bounds[], int index[],
528 int pair[], int nbounds,
529 const gmx_output_env_t *oenv)
531 FILE *vout;
532 double sum, sumt, sumaver;
533 int i, j;
535 /* Subtract bounds from distances, to calculate violations */
536 calc_violations(violaver, violaver,
537 nbounds, pair, bounds, NULL, &sumt, &sumaver);
539 #ifdef DEBUG
540 fprintf(stdout, "\nSum of violations averaged over simulation: %g nm\n",
541 sumaver);
542 fprintf(stdout, "Largest violation averaged over simulation: %g nm\n\n",
543 sumt);
544 #endif
545 vout = xvgropen(voutfn, "r\\S-3\\N average violations", "DR Index", "nm",
546 oenv);
547 sum = 0.0;
548 sumt = 0.0;
549 for (i = 0; (i < nbounds); i++)
551 /* Do ensemble averaging */
552 sumaver = 0;
553 for (j = pair[i]; (j < pair[i+1]); j++)
555 sumaver += gmx::square(violaver[j]/nframes);
557 sumaver = std::max(0.0, mypow(sumaver, minsixth)-bounds[i]);
559 sumt += sumaver;
560 sum = std::max(sum, sumaver);
561 fprintf(vout, "%10d %10.5e\n", index[i], sumaver);
563 #ifdef DEBUG
564 for (j = 0; (j < dr.ndr); j++)
566 fprintf(vout, "%10d %10.5e\n", j, mypow(violaver[j]/nframes, minthird));
568 #endif
569 xvgrclose(vout);
571 fprintf(stdout, "\nSum of violations averaged over simulation: %g nm\n",
572 sumt);
573 fprintf(stdout, "Largest violation averaged over simulation: %g nm\n\n", sum);
575 do_view(oenv, voutfn, "-graphtype bar");
578 static void einstein_visco(const char *fn, const char *fni, int nsets,
579 int nint, real **eneint,
580 real V, real T, double dt,
581 const gmx_output_env_t *oenv)
583 FILE *fp0, *fp1;
584 double av[4], avold[4];
585 double fac, di;
586 int i, j, m, nf4;
588 nf4 = nint/4 + 1;
590 for (i = 0; i <= nsets; i++)
592 avold[i] = 0;
594 fp0 = xvgropen(fni, "Shear viscosity integral",
595 "Time (ps)", "(kg m\\S-1\\N s\\S-1\\N ps)", oenv);
596 fp1 = xvgropen(fn, "Shear viscosity using Einstein relation",
597 "Time (ps)", "(kg m\\S-1\\N s\\S-1\\N)", oenv);
598 for (i = 0; i < nf4; i++)
600 for (m = 0; m <= nsets; m++)
602 av[m] = 0;
604 for (j = 0; j < nint - i; j++)
606 for (m = 0; m < nsets; m++)
608 di = gmx::square(eneint[m][j+i] - eneint[m][j]);
610 av[m] += di;
611 av[nsets] += di/nsets;
614 /* Convert to SI for the viscosity */
615 fac = (V*NANO*NANO*NANO*PICO*1e10)/(2*BOLTZMANN*T)/(nint - i);
616 fprintf(fp0, "%10g", i*dt);
617 for (m = 0; (m <= nsets); m++)
619 av[m] = fac*av[m];
620 fprintf(fp0, " %10g", av[m]);
622 fprintf(fp0, "\n");
623 fprintf(fp1, "%10g", (i + 0.5)*dt);
624 for (m = 0; (m <= nsets); m++)
626 fprintf(fp1, " %10g", (av[m]-avold[m])/dt);
627 avold[m] = av[m];
629 fprintf(fp1, "\n");
631 xvgrclose(fp0);
632 xvgrclose(fp1);
635 typedef struct {
636 gmx_int64_t np;
637 double sum;
638 double sav;
639 double sav2;
640 } ee_sum_t;
642 typedef struct {
643 int b;
644 ee_sum_t sum;
645 gmx_int64_t nst;
646 gmx_int64_t nst_min;
647 } ener_ee_t;
649 static void clear_ee_sum(ee_sum_t *ees)
651 ees->sav = 0;
652 ees->sav2 = 0;
653 ees->np = 0;
654 ees->sum = 0;
657 static void add_ee_sum(ee_sum_t *ees, double sum, int np)
659 ees->np += np;
660 ees->sum += sum;
663 static void add_ee_av(ee_sum_t *ees)
665 double av;
667 av = ees->sum/ees->np;
668 ees->sav += av;
669 ees->sav2 += av*av;
670 ees->np = 0;
671 ees->sum = 0;
674 static double calc_ee2(int nb, ee_sum_t *ees)
676 return (ees->sav2/nb - gmx::square(ees->sav/nb))/(nb - 1);
679 static void set_ee_av(ener_ee_t *eee)
681 if (debug)
683 char buf[STEPSTRSIZE];
684 fprintf(debug, "Storing average for err.est.: %s steps\n",
685 gmx_step_str(eee->nst, buf));
687 add_ee_av(&eee->sum);
688 eee->b++;
689 if (eee->b == 1 || eee->nst < eee->nst_min)
691 eee->nst_min = eee->nst;
693 eee->nst = 0;
696 static void calc_averages(int nset, enerdata_t *edat, int nbmin, int nbmax)
698 int nb, i, f, nee;
699 double sum, sum2, sump, see2;
700 gmx_int64_t np, p, bound_nb;
701 enerdat_t *ed;
702 exactsum_t *es;
703 gmx_bool bAllZero;
704 double x, sx, sy, sxx, sxy;
705 ener_ee_t *eee;
707 /* Check if we have exact statistics over all points */
708 for (i = 0; i < nset; i++)
710 ed = &edat->s[i];
711 ed->bExactStat = FALSE;
712 if (edat->bHaveSums)
714 /* All energy file sum entries 0 signals no exact sums.
715 * But if all energy values are 0, we still have exact sums.
717 bAllZero = TRUE;
718 for (f = 0; f < edat->nframes && !ed->bExactStat; f++)
720 if (ed->ener[i] != 0)
722 bAllZero = FALSE;
724 ed->bExactStat = (ed->es[f].sum != 0);
726 if (bAllZero)
728 ed->bExactStat = TRUE;
733 snew(eee, nbmax+1);
734 for (i = 0; i < nset; i++)
736 ed = &edat->s[i];
738 sum = 0;
739 sum2 = 0;
740 np = 0;
741 sx = 0;
742 sy = 0;
743 sxx = 0;
744 sxy = 0;
745 for (nb = nbmin; nb <= nbmax; nb++)
747 eee[nb].b = 0;
748 clear_ee_sum(&eee[nb].sum);
749 eee[nb].nst = 0;
750 eee[nb].nst_min = 0;
752 for (f = 0; f < edat->nframes; f++)
754 es = &ed->es[f];
756 if (ed->bExactStat)
758 /* Add the sum and the sum of variances to the totals. */
759 p = edat->points[f];
760 sump = es->sum;
761 sum2 += es->sum2;
762 if (np > 0)
764 sum2 += gmx::square(sum/np - (sum + es->sum)/(np + p))
765 *np*(np + p)/p;
768 else
770 /* Add a single value to the sum and sum of squares. */
771 p = 1;
772 sump = ed->ener[f];
773 sum2 += gmx::square(sump);
776 /* sum has to be increased after sum2 */
777 np += p;
778 sum += sump;
780 /* For the linear regression use variance 1/p.
781 * Note that sump is the sum, not the average, so we don't need p*.
783 x = edat->step[f] - 0.5*(edat->steps[f] - 1);
784 sx += p*x;
785 sy += sump;
786 sxx += p*x*x;
787 sxy += x*sump;
789 for (nb = nbmin; nb <= nbmax; nb++)
791 /* Check if the current end step is closer to the desired
792 * block boundary than the next end step.
794 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
795 if (eee[nb].nst > 0 &&
796 bound_nb - edat->step[f-1]*nb < edat->step[f]*nb - bound_nb)
798 set_ee_av(&eee[nb]);
800 if (f == 0)
802 eee[nb].nst = 1;
804 else
806 eee[nb].nst += edat->step[f] - edat->step[f-1];
808 if (ed->bExactStat)
810 add_ee_sum(&eee[nb].sum, es->sum, edat->points[f]);
812 else
814 add_ee_sum(&eee[nb].sum, edat->s[i].ener[f], 1);
816 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
817 if (edat->step[f]*nb >= bound_nb)
819 set_ee_av(&eee[nb]);
824 edat->s[i].av = sum/np;
825 if (ed->bExactStat)
827 edat->s[i].rmsd = std::sqrt(sum2/np);
829 else
831 edat->s[i].rmsd = std::sqrt(sum2/np - gmx::square(edat->s[i].av));
834 if (edat->nframes > 1)
836 edat->s[i].slope = (np*sxy - sx*sy)/(np*sxx - sx*sx);
838 else
840 edat->s[i].slope = 0;
843 nee = 0;
844 see2 = 0;
845 for (nb = nbmin; nb <= nbmax; nb++)
847 /* Check if we actually got nb blocks and if the smallest
848 * block is not shorter than 80% of the average.
850 if (debug)
852 char buf1[STEPSTRSIZE], buf2[STEPSTRSIZE];
853 fprintf(debug, "Requested %d blocks, we have %d blocks, min %s nsteps %s\n",
854 nb, eee[nb].b,
855 gmx_step_str(eee[nb].nst_min, buf1),
856 gmx_step_str(edat->nsteps, buf2));
858 if (eee[nb].b == nb && 5*nb*eee[nb].nst_min >= 4*edat->nsteps)
860 see2 += calc_ee2(nb, &eee[nb].sum);
861 nee++;
864 if (nee > 0)
866 edat->s[i].ee = std::sqrt(see2/nee);
868 else
870 edat->s[i].ee = -1;
873 sfree(eee);
876 static enerdata_t *calc_sum(int nset, enerdata_t *edat, int nbmin, int nbmax)
878 enerdata_t *esum;
879 enerdat_t *s;
880 int f, i;
881 double sum;
883 snew(esum, 1);
884 *esum = *edat;
885 snew(esum->s, 1);
886 s = &esum->s[0];
887 snew(s->ener, esum->nframes);
888 snew(s->es, esum->nframes);
890 s->bExactStat = TRUE;
891 s->slope = 0;
892 for (i = 0; i < nset; i++)
894 if (!edat->s[i].bExactStat)
896 s->bExactStat = FALSE;
898 s->slope += edat->s[i].slope;
901 for (f = 0; f < edat->nframes; f++)
903 sum = 0;
904 for (i = 0; i < nset; i++)
906 sum += edat->s[i].ener[f];
908 s->ener[f] = sum;
909 sum = 0;
910 for (i = 0; i < nset; i++)
912 sum += edat->s[i].es[f].sum;
914 s->es[f].sum = sum;
915 s->es[f].sum2 = 0;
918 calc_averages(1, esum, nbmin, nbmax);
920 return esum;
923 static char *ee_pr(double ee, char *buf)
925 char tmp[100];
926 double rnd;
928 if (ee < 0)
930 sprintf(buf, "%s", "--");
932 else
934 /* Round to two decimals by printing. */
935 sprintf(tmp, "%.1e", ee);
936 sscanf(tmp, "%lf", &rnd);
937 sprintf(buf, "%g", rnd);
940 return buf;
943 static void remove_drift(int nset, int nbmin, int nbmax, real dt, enerdata_t *edat)
945 /* Remove the drift by performing a fit to y = ax+b.
946 Uses 5 iterations. */
947 int i, j, k;
948 double delta;
950 edat->npoints = edat->nframes;
951 edat->nsteps = edat->nframes;
953 for (k = 0; (k < 5); k++)
955 for (i = 0; (i < nset); i++)
957 delta = edat->s[i].slope*dt;
959 if (NULL != debug)
961 fprintf(debug, "slope for set %d is %g\n", i, edat->s[i].slope);
964 for (j = 0; (j < edat->nframes); j++)
966 edat->s[i].ener[j] -= j*delta;
967 edat->s[i].es[j].sum = 0;
968 edat->s[i].es[j].sum2 = 0;
971 calc_averages(nset, edat, nbmin, nbmax);
975 static void calc_fluctuation_props(FILE *fp,
976 gmx_bool bDriftCorr, real dt,
977 int nset, int nmol,
978 char **leg, enerdata_t *edat,
979 int nbmin, int nbmax)
981 int i, j;
982 double vv, v, h, varv, hh, varh, tt, cv, cp, alpha, kappa, dcp, varet;
983 double NANO3;
984 enum {
985 eVol, eEnth, eTemp, eEtot, eNR
987 const char *my_ener[] = { "Volume", "Enthalpy", "Temperature", "Total Energy" };
988 int ii[eNR];
990 NANO3 = NANO*NANO*NANO;
991 if (!bDriftCorr)
993 fprintf(fp, "\nYou may want to use the -driftcorr flag in order to correct\n"
994 "for spurious drift in the graphs. Note that this is not\n"
995 "a substitute for proper equilibration and sampling!\n");
997 else
999 remove_drift(nset, nbmin, nbmax, dt, edat);
1001 for (i = 0; (i < eNR); i++)
1003 for (ii[i] = 0; (ii[i] < nset &&
1004 (gmx_strcasecmp(leg[ii[i]], my_ener[i]) != 0)); ii[i]++)
1008 /* if (ii[i] < nset)
1009 fprintf(fp,"Found %s data.\n",my_ener[i]);
1010 */ }
1011 /* Compute it all! */
1012 alpha = kappa = cp = dcp = cv = NOTSET;
1014 /* Temperature */
1015 tt = NOTSET;
1016 if (ii[eTemp] < nset)
1018 tt = edat->s[ii[eTemp]].av;
1020 /* Volume */
1021 vv = varv = NOTSET;
1022 if ((ii[eVol] < nset) && (ii[eTemp] < nset))
1024 vv = edat->s[ii[eVol]].av*NANO3;
1025 varv = gmx::square(edat->s[ii[eVol]].rmsd*NANO3);
1026 kappa = (varv/vv)/(BOLTZMANN*tt);
1028 /* Enthalpy */
1029 hh = varh = NOTSET;
1030 if ((ii[eEnth] < nset) && (ii[eTemp] < nset))
1032 hh = KILO*edat->s[ii[eEnth]].av/AVOGADRO;
1033 varh = gmx::square(KILO*edat->s[ii[eEnth]].rmsd/AVOGADRO);
1034 cp = AVOGADRO*((varh/nmol)/(BOLTZMANN*tt*tt));
1036 /* Total energy */
1037 if ((ii[eEtot] < nset) && (hh == NOTSET) && (tt != NOTSET))
1039 /* Only compute cv in constant volume runs, which we can test
1040 by checking whether the enthalpy was computed.
1042 varet = gmx::square(edat->s[ii[eEtot]].rmsd);
1043 cv = KILO*((varet/nmol)/(BOLTZ*tt*tt));
1045 /* Alpha, dcp */
1046 if ((ii[eVol] < nset) && (ii[eEnth] < nset) && (ii[eTemp] < nset))
1048 double v_sum, h_sum, vh_sum, v_aver, h_aver, vh_aver;
1049 vh_sum = v_sum = h_sum = 0;
1050 for (j = 0; (j < edat->nframes); j++)
1052 v = edat->s[ii[eVol]].ener[j]*NANO3;
1053 h = KILO*edat->s[ii[eEnth]].ener[j]/AVOGADRO;
1054 v_sum += v;
1055 h_sum += h;
1056 vh_sum += (v*h);
1058 vh_aver = vh_sum / edat->nframes;
1059 v_aver = v_sum / edat->nframes;
1060 h_aver = h_sum / edat->nframes;
1061 alpha = (vh_aver-v_aver*h_aver)/(v_aver*BOLTZMANN*tt*tt);
1062 dcp = (v_aver*AVOGADRO/nmol)*tt*gmx::square(alpha)/(kappa);
1065 if (tt != NOTSET)
1067 if (nmol < 2)
1069 fprintf(fp, "\nWARNING: nmol = %d, this may not be what you want.\n",
1070 nmol);
1072 fprintf(fp, "\nTemperature dependent fluctuation properties at T = %g.\n", tt);
1073 fprintf(fp, "\nHeat capacities obtained from fluctuations do *not* include\n");
1074 fprintf(fp, "quantum corrections. If you want to get a more accurate estimate\n");
1075 fprintf(fp, "please use the g_dos program.\n\n");
1076 fprintf(fp, "WARNING: Please verify that your simulations are converged and perform\n"
1077 "a block-averaging error analysis (not implemented in g_energy yet)\n");
1079 if (debug != NULL)
1081 if (varv != NOTSET)
1083 fprintf(fp, "varv = %10g (m^6)\n", varv*AVOGADRO/nmol);
1086 if (vv != NOTSET)
1088 fprintf(fp, "Volume = %10g m^3/mol\n",
1089 vv*AVOGADRO/nmol);
1091 if (varh != NOTSET)
1093 fprintf(fp, "Enthalpy = %10g kJ/mol\n",
1094 hh*AVOGADRO/(KILO*nmol));
1096 if (alpha != NOTSET)
1098 fprintf(fp, "Coefficient of Thermal Expansion Alpha_P = %10g (1/K)\n",
1099 alpha);
1101 if (kappa != NOTSET)
1103 fprintf(fp, "Isothermal Compressibility Kappa = %10g (m^3/J)\n",
1104 kappa);
1105 fprintf(fp, "Adiabatic bulk modulus = %10g (J/m^3)\n",
1106 1.0/kappa);
1108 if (cp != NOTSET)
1110 fprintf(fp, "Heat capacity at constant pressure Cp = %10g J/(mol K)\n",
1111 cp);
1113 if (cv != NOTSET)
1115 fprintf(fp, "Heat capacity at constant volume Cv = %10g J/(mol K)\n",
1116 cv);
1118 if (dcp != NOTSET)
1120 fprintf(fp, "Cp-Cv = %10g J/(mol K)\n",
1121 dcp);
1123 please_cite(fp, "Allen1987a");
1125 else
1127 fprintf(fp, "You should select the temperature in order to obtain fluctuation properties.\n");
1131 static void analyse_ener(gmx_bool bCorr, const char *corrfn,
1132 gmx_bool bFee, gmx_bool bSum, gmx_bool bFluct,
1133 gmx_bool bVisco, const char *visfn, int nmol,
1134 gmx_int64_t start_step, double start_t,
1135 gmx_int64_t step, double t,
1136 real reftemp,
1137 enerdata_t *edat,
1138 int nset, int set[], gmx_bool *bIsEner,
1139 char **leg, gmx_enxnm_t *enm,
1140 real Vaver, real ezero,
1141 int nbmin, int nbmax,
1142 const gmx_output_env_t *oenv)
1144 FILE *fp;
1145 /* Check out the printed manual for equations! */
1146 double Dt, aver, stddev, errest, delta_t, totaldrift;
1147 enerdata_t *esum = NULL;
1148 real integral, intBulk, Temp = 0, Pres = 0;
1149 real pr_aver, pr_stddev, pr_errest;
1150 double beta = 0, expE, expEtot, *fee = NULL;
1151 gmx_int64_t nsteps;
1152 int nexact, nnotexact;
1153 int i, j, nout;
1154 char buf[256], eebuf[100];
1156 nsteps = step - start_step + 1;
1157 if (nsteps < 1)
1159 fprintf(stdout, "Not enough steps (%s) for statistics\n",
1160 gmx_step_str(nsteps, buf));
1162 else
1164 /* Calculate the time difference */
1165 delta_t = t - start_t;
1167 fprintf(stdout, "\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
1168 gmx_step_str(nsteps, buf), start_t, t, nset);
1170 calc_averages(nset, edat, nbmin, nbmax);
1172 if (bSum)
1174 esum = calc_sum(nset, edat, nbmin, nbmax);
1177 if (!edat->bHaveSums)
1179 nexact = 0;
1180 nnotexact = nset;
1182 else
1184 nexact = 0;
1185 nnotexact = 0;
1186 for (i = 0; (i < nset); i++)
1188 if (edat->s[i].bExactStat)
1190 nexact++;
1192 else
1194 nnotexact++;
1199 if (nnotexact == 0)
1201 fprintf(stdout, "All statistics are over %s points\n",
1202 gmx_step_str(edat->npoints, buf));
1204 else if (nexact == 0 || edat->npoints == edat->nframes)
1206 fprintf(stdout, "All statistics are over %d points (frames)\n",
1207 edat->nframes);
1209 else
1211 fprintf(stdout, "The term%s", nnotexact == 1 ? "" : "s");
1212 for (i = 0; (i < nset); i++)
1214 if (!edat->s[i].bExactStat)
1216 fprintf(stdout, " '%s'", leg[i]);
1219 fprintf(stdout, " %s has statistics over %d points (frames)\n",
1220 nnotexact == 1 ? "is" : "are", edat->nframes);
1221 fprintf(stdout, "All other statistics are over %s points\n",
1222 gmx_step_str(edat->npoints, buf));
1224 fprintf(stdout, "\n");
1226 fprintf(stdout, "%-24s %10s %10s %10s %10s",
1227 "Energy", "Average", "Err.Est.", "RMSD", "Tot-Drift");
1228 if (bFee)
1230 fprintf(stdout, " %10s\n", "-kT ln<e^(E/kT)>");
1232 else
1234 fprintf(stdout, "\n");
1236 fprintf(stdout, "-------------------------------------------------------------------------------\n");
1238 /* Initiate locals, only used with -sum */
1239 expEtot = 0;
1240 if (bFee)
1242 beta = 1.0/(BOLTZ*reftemp);
1243 snew(fee, nset);
1245 for (i = 0; (i < nset); i++)
1247 aver = edat->s[i].av;
1248 stddev = edat->s[i].rmsd;
1249 errest = edat->s[i].ee;
1251 if (bFee)
1253 expE = 0;
1254 for (j = 0; (j < edat->nframes); j++)
1256 expE += std::exp(beta*(edat->s[i].ener[j] - aver)/nmol);
1258 if (bSum)
1260 expEtot += expE/edat->nframes;
1263 fee[i] = std::log(expE/edat->nframes)/beta + aver/nmol;
1265 if (std::strstr(leg[i], "empera") != NULL)
1267 Temp = aver;
1269 else if (std::strstr(leg[i], "olum") != NULL)
1271 Vaver = aver;
1273 else if (std::strstr(leg[i], "essure") != NULL)
1275 Pres = aver;
1277 if (bIsEner[i])
1279 pr_aver = aver/nmol-ezero;
1280 pr_stddev = stddev/nmol;
1281 pr_errest = errest/nmol;
1283 else
1285 pr_aver = aver;
1286 pr_stddev = stddev;
1287 pr_errest = errest;
1290 /* Multiply the slope in steps with the number of steps taken */
1291 totaldrift = (edat->nsteps - 1)*edat->s[i].slope;
1292 if (bIsEner[i])
1294 totaldrift /= nmol;
1297 fprintf(stdout, "%-24s %10g %10s %10g %10g",
1298 leg[i], pr_aver, ee_pr(pr_errest, eebuf), pr_stddev, totaldrift);
1299 if (bFee)
1301 fprintf(stdout, " %10g", fee[i]);
1304 fprintf(stdout, " (%s)\n", enm[set[i]].unit);
1306 if (bFluct)
1308 for (j = 0; (j < edat->nframes); j++)
1310 edat->s[i].ener[j] -= aver;
1314 if (bSum)
1316 totaldrift = (edat->nsteps - 1)*esum->s[0].slope;
1317 fprintf(stdout, "%-24s %10g %10s %10s %10g (%s)",
1318 "Total", esum->s[0].av/nmol, ee_pr(esum->s[0].ee/nmol, eebuf),
1319 "--", totaldrift/nmol, enm[set[0]].unit);
1320 /* pr_aver,pr_stddev,a,totaldrift */
1321 if (bFee)
1323 fprintf(stdout, " %10g %10g\n",
1324 std::log(expEtot)/beta + esum->s[0].av/nmol, std::log(expEtot)/beta);
1326 else
1328 fprintf(stdout, "\n");
1332 /* Do correlation function */
1333 if (edat->nframes > 1)
1335 Dt = delta_t/(edat->nframes - 1);
1337 else
1339 Dt = 0;
1341 if (bVisco)
1343 const char* leg[] = { "Shear", "Bulk" };
1344 real factor;
1345 real **eneset;
1346 real **eneint;
1348 /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
1350 /* Symmetrise tensor! (and store in first three elements)
1351 * And subtract average pressure!
1353 snew(eneset, 12);
1354 for (i = 0; i < 12; i++)
1356 snew(eneset[i], edat->nframes);
1358 for (i = 0; (i < edat->nframes); i++)
1360 eneset[0][i] = 0.5*(edat->s[1].ener[i]+edat->s[3].ener[i]);
1361 eneset[1][i] = 0.5*(edat->s[2].ener[i]+edat->s[6].ener[i]);
1362 eneset[2][i] = 0.5*(edat->s[5].ener[i]+edat->s[7].ener[i]);
1363 for (j = 3; j <= 11; j++)
1365 eneset[j][i] = edat->s[j].ener[i];
1367 eneset[11][i] -= Pres;
1370 /* Determine integrals of the off-diagonal pressure elements */
1371 snew(eneint, 3);
1372 for (i = 0; i < 3; i++)
1374 snew(eneint[i], edat->nframes + 1);
1376 eneint[0][0] = 0;
1377 eneint[1][0] = 0;
1378 eneint[2][0] = 0;
1379 for (i = 0; i < edat->nframes; i++)
1381 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];
1382 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];
1383 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];
1386 einstein_visco("evisco.xvg", "eviscoi.xvg",
1387 3, edat->nframes+1, eneint, Vaver, Temp, Dt, oenv);
1389 for (i = 0; i < 3; i++)
1391 sfree(eneint[i]);
1393 sfree(eneint);
1395 /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
1396 /* Do it for shear viscosity */
1397 std::strcpy(buf, "Shear Viscosity");
1398 low_do_autocorr(corrfn, oenv, buf, edat->nframes, 3,
1399 (edat->nframes+1)/2, eneset, Dt,
1400 eacNormal, 1, TRUE, FALSE, FALSE, 0.0, 0.0, 0);
1402 /* Now for bulk viscosity */
1403 std::strcpy(buf, "Bulk Viscosity");
1404 low_do_autocorr(corrfn, oenv, buf, edat->nframes, 1,
1405 (edat->nframes+1)/2, &(eneset[11]), Dt,
1406 eacNormal, 1, TRUE, FALSE, FALSE, 0.0, 0.0, 0);
1408 factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
1409 fp = xvgropen(visfn, buf, "Time (ps)", "\\8h\\4 (cp)", oenv);
1410 xvgr_legend(fp, asize(leg), leg, oenv);
1412 /* Use trapezium rule for integration */
1413 integral = 0;
1414 intBulk = 0;
1415 nout = get_acfnout();
1416 if ((nout < 2) || (nout >= edat->nframes/2))
1418 nout = edat->nframes/2;
1420 for (i = 1; (i < nout); i++)
1422 integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
1423 intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
1424 fprintf(fp, "%10g %10g %10g\n", (i*Dt), integral, intBulk);
1426 xvgrclose(fp);
1428 for (i = 0; i < 12; i++)
1430 sfree(eneset[i]);
1432 sfree(eneset);
1434 else if (bCorr)
1436 if (bFluct)
1438 std::strcpy(buf, "Autocorrelation of Energy Fluctuations");
1440 else
1442 std::strcpy(buf, "Energy Autocorrelation");
1444 #if 0
1445 do_autocorr(corrfn, oenv, buf, edat->nframes,
1446 bSum ? 1 : nset,
1447 bSum ? &edat->s[nset-1].ener : eneset,
1448 (delta_t/edat->nframes), eacNormal, FALSE);
1449 #endif
1454 static void print_time(FILE *fp, double t)
1456 fprintf(fp, "%12.6f", t);
1459 static void print1(FILE *fp, gmx_bool bDp, real e)
1461 if (bDp)
1463 fprintf(fp, " %16.12f", e);
1465 else
1467 fprintf(fp, " %10.6f", e);
1471 static void fec(const char *ene2fn, const char *runavgfn,
1472 real reftemp, int nset, int set[], char *leg[],
1473 enerdata_t *edat, double time[],
1474 const gmx_output_env_t *oenv)
1476 const char * ravgleg[] = {
1477 "\\8D\\4E = E\\sB\\N-E\\sA\\N",
1478 "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N"
1480 FILE *fp;
1481 ener_file_t enx;
1482 int timecheck, nenergy, nenergy2, maxenergy;
1483 int i, j;
1484 gmx_bool bCont;
1485 real aver, beta;
1486 real **eneset2;
1487 double dE, sum;
1488 gmx_enxnm_t *enm = NULL;
1489 t_enxframe *fr;
1490 char buf[22];
1492 /* read second energy file */
1493 snew(fr, 1);
1494 enm = NULL;
1495 enx = open_enx(ene2fn, "r");
1496 do_enxnms(enx, &(fr->nre), &enm);
1498 snew(eneset2, nset+1);
1499 nenergy2 = 0;
1500 maxenergy = 0;
1501 timecheck = 0;
1504 /* This loop searches for the first frame (when -b option is given),
1505 * or when this has been found it reads just one energy frame
1509 bCont = do_enx(enx, fr);
1511 if (bCont)
1513 timecheck = check_times(fr->t);
1517 while (bCont && (timecheck < 0));
1519 /* Store energies for analysis afterwards... */
1520 if ((timecheck == 0) && bCont)
1522 if (fr->nre > 0)
1524 if (nenergy2 >= maxenergy)
1526 maxenergy += 1000;
1527 for (i = 0; i <= nset; i++)
1529 srenew(eneset2[i], maxenergy);
1532 GMX_RELEASE_ASSERT(time != NULL, "trying to dereference NULL time pointer");
1534 if (fr->t != time[nenergy2])
1536 fprintf(stderr, "\nWARNING time mismatch %g!=%g at frame %s\n",
1537 fr->t, time[nenergy2], gmx_step_str(fr->step, buf));
1539 for (i = 0; i < nset; i++)
1541 eneset2[i][nenergy2] = fr->ener[set[i]].e;
1543 nenergy2++;
1547 while (bCont && (timecheck == 0));
1549 /* check */
1550 if (edat->nframes != nenergy2)
1552 fprintf(stderr, "\nWARNING file length mismatch %d!=%d\n",
1553 edat->nframes, nenergy2);
1555 nenergy = std::min(edat->nframes, nenergy2);
1557 /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
1558 fp = NULL;
1559 if (runavgfn)
1561 fp = xvgropen(runavgfn, "Running average free energy difference",
1562 "Time (" unit_time ")", "\\8D\\4E (" unit_energy ")", oenv);
1563 xvgr_legend(fp, asize(ravgleg), ravgleg, oenv);
1565 fprintf(stdout, "\n%-24s %10s\n",
1566 "Energy", "dF = -kT ln < exp(-(EB-EA)/kT) >A");
1567 sum = 0;
1568 beta = 1.0/(BOLTZ*reftemp);
1569 for (i = 0; i < nset; i++)
1571 if (gmx_strcasecmp(leg[i], enm[set[i]].name) != 0)
1573 fprintf(stderr, "\nWARNING energy set name mismatch %s!=%s\n",
1574 leg[i], enm[set[i]].name);
1576 for (j = 0; j < nenergy; j++)
1578 dE = eneset2[i][j] - edat->s[i].ener[j];
1579 sum += std::exp(-dE*beta);
1580 if (fp)
1582 fprintf(fp, "%10g %10g %10g\n",
1583 time[j], dE, -BOLTZ*reftemp*std::log(sum/(j+1)) );
1586 aver = -BOLTZ*reftemp*std::log(sum/nenergy);
1587 fprintf(stdout, "%-24s %10g\n", leg[i], aver);
1589 if (fp)
1591 xvgrclose(fp);
1593 sfree(fr);
1597 static void do_dhdl(t_enxframe *fr, const t_inputrec *ir, FILE **fp_dhdl,
1598 const char *filename, gmx_bool bDp,
1599 int *blocks, int *hists, int *samples, int *nlambdas,
1600 const gmx_output_env_t *oenv)
1602 const char *dhdl = "dH/d\\lambda", *deltag = "\\DeltaH", *lambda = "\\lambda";
1603 char title[STRLEN], label_x[STRLEN], label_y[STRLEN], legend[STRLEN];
1604 char buf[STRLEN];
1605 int nblock_hist = 0, nblock_dh = 0, nblock_dhcoll = 0;
1606 int i, j, k;
1607 /* coll data */
1608 double temp = 0, start_time = 0, delta_time = 0, start_lambda = 0;
1609 static int setnr = 0;
1610 double *native_lambda_vec = NULL;
1611 const char **lambda_components = NULL;
1612 int n_lambda_vec = 0;
1613 bool firstPass = true;
1615 /* now count the blocks & handle the global dh data */
1616 for (i = 0; i < fr->nblock; i++)
1618 if (fr->block[i].id == enxDHHIST)
1620 nblock_hist++;
1622 else if (fr->block[i].id == enxDH)
1624 nblock_dh++;
1626 else if (fr->block[i].id == enxDHCOLL)
1628 nblock_dhcoll++;
1629 if ( (fr->block[i].nsub < 1) ||
1630 (fr->block[i].sub[0].type != xdr_datatype_double) ||
1631 (fr->block[i].sub[0].nr < 5))
1633 gmx_fatal(FARGS, "Unexpected block data");
1636 /* read the data from the DHCOLL block */
1637 temp = fr->block[i].sub[0].dval[0];
1638 start_time = fr->block[i].sub[0].dval[1];
1639 delta_time = fr->block[i].sub[0].dval[2];
1640 start_lambda = fr->block[i].sub[0].dval[3];
1641 if (fr->block[i].nsub > 1)
1643 if (firstPass)
1645 n_lambda_vec = fr->block[i].sub[1].ival[1];
1646 snew(lambda_components, n_lambda_vec);
1647 snew(native_lambda_vec, n_lambda_vec);
1648 firstPass = false;
1650 else
1652 if (n_lambda_vec != fr->block[i].sub[1].ival[1])
1654 gmx_fatal(FARGS,
1655 "Unexpected change of basis set in lambda");
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 */
1671 return;
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.");
1677 if (!*fp_dhdl)
1679 if (nblock_dh > 0)
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
1686 the ener.edr. */
1687 *fp_dhdl = open_dhdl(filename, ir, oenv);
1689 else
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;
1708 /* histograms */
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;
1715 gmx_int64_t x0;
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++)
1733 const char *lg[1];
1734 x0 = blk->sub[1].lval[2+j];
1736 if (!derivative)
1738 sprintf(legend, "N(%s(%s=%g) | %s=%g)",
1739 deltag, lambda, foreign_lambda,
1740 lambda, start_lambda);
1742 else
1744 sprintf(legend, "N(%s | %s=%g)",
1745 dhdl, lambda, start_lambda);
1748 lg[0] = legend;
1749 xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv);
1750 setnr++;
1751 for (k = 0; k < blk->sub[j+2].nr; k++)
1753 int hist;
1754 double xmin, xmax;
1756 hist = blk->sub[j+2].ival[k];
1757 xmin = (x0+k)*dx;
1758 xmax = (x0+k+1)*dx;
1759 fprintf(*fp_dhdl, "%g %d\n%g %d\n", xmin, hist,
1760 xmax, hist);
1761 sum += 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 */
1767 dx = -dx;
1771 (*samples) += static_cast<int>(sum/nblock_hist);
1773 else
1775 /* raw dh */
1776 int len = 0;
1778 for (i = 0; i < fr->nblock; i++)
1780 t_enxblock *blk = &(fr->block[i]);
1781 if (blk->id == enxDH)
1783 if (len == 0)
1785 len = blk->sub[2].nr;
1787 else
1789 if (len != blk->sub[2].nr)
1791 gmx_fatal(FARGS, "Length inconsistency in dhdl data");
1796 (*samples) += len;
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)
1809 double value;
1810 if (blk->sub[2].type == xdr_datatype_float)
1812 value = blk->sub[2].fval[i];
1814 else
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! */
1824 else
1826 if (bDp)
1828 fprintf(*fp_dhdl, " %#.12g", value); /* print normal precision */
1830 else
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",
1924 "estimate using::",
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;
1945 t_pargs pa[] = {
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[] = {
1980 "Running average",
1981 "Instantaneous"
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;
1991 ener_file_t fp;
1992 int timecheck = 0;
1993 gmx_mtop_t mtop;
1994 gmx_localtop_t *top = NULL;
1995 t_inputrec ir;
1996 enerdata_t edat;
1997 gmx_enxnm_t *enm = NULL;
1998 t_enxframe *frame, *fr = NULL;
1999 int cur = 0;
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;
2004 real start_t;
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;
2012 real Vaver;
2013 int *set = NULL, i, j, k, nset, sss;
2014 gmx_bool *bIsEner = NULL;
2015 char **pairleg, **odtleg, **otenleg;
2016 char **leg = NULL;
2017 char *anm_j, *anm_k, *resnm_j, *resnm_k;
2018 int resnr_j, resnr_k;
2019 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
2020 char buf[256];
2021 gmx_output_env_t *oenv;
2022 t_enxblock *blk = NULL;
2023 t_enxblock *blk_disre = NULL;
2024 int ndisre = 0;
2025 int dh_blocks = 0, dh_hists = 0, dh_samples = 0, dh_lambdas = 0;
2027 t_filenm fnm[] = {
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)
2046 int npargs;
2047 t_pargs *ppa;
2049 npargs = asize(pa);
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))
2055 return 0;
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);
2069 nset = 0;
2071 snew(frame, 2);
2072 fp = open_enx(ftp2fn(efEDR, NFILE, fnm), "r");
2073 do_enxnms(fp, &nre, &enm);
2075 Vaver = -1;
2077 bVisco = opt2bSet("-vis", NFILE, fnm);
2079 if ((!bDisRe) && (!bDHDL))
2081 if (bVisco)
2083 nset = asize(setnm);
2084 snew(set, nset);
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]))
2092 set[j] = i;
2093 break;
2096 if (i == nre)
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");
2105 Vaver = dbl;
2107 else
2109 gmx_fatal(FARGS, "Could not find term %s for viscosity calculation",
2110 setnm[j]);
2115 else
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)
2127 break;
2130 if (j == i)
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,
2138 oenv);
2140 snew(leg, nset+1);
2141 for (i = 0; (i < nset); i++)
2143 leg[i] = enm[set[i]].name;
2145 if (bSum)
2147 leg[nset] = gmx_strdup("Sum");
2148 xvgr_legend(out, nset+1, (const char**)leg, oenv);
2150 else
2152 xvgr_legend(out, nset, (const char**)leg, oenv);
2155 snew(bIsEner, nset);
2156 for (i = 0; (i < nset); i++)
2158 bIsEner[i] = FALSE;
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");
2171 time = NULL;
2173 if (bORIRE || bOTEN)
2175 get_orires_parms(ftp2fn(efTPR, NFILE, fnm), &nor, &nex, &or_label, &oobs);
2178 if (bORIRE)
2180 if (bOrinst)
2182 enx_i = enxORI;
2184 else
2186 enx_i = enxOR;
2189 if (bORA || bODA)
2191 snew(orient, nor);
2193 if (bODR)
2195 snew(odrms, nor);
2197 if (bORT || bODT)
2199 fprintf(stderr, "Select the orientation restraint labels you want (-1 is all)\n");
2200 fprintf(stderr, "End your selection with 0\n");
2201 j = -1;
2202 orsel = NULL;
2205 j++;
2206 srenew(orsel, j+1);
2207 if (1 != scanf("%d", &(orsel[j])))
2209 gmx_fatal(FARGS, "Error reading user input");
2212 while (orsel[j] > 0);
2213 if (orsel[0] == -1)
2215 fprintf(stderr, "Selecting all %d orientation restraints\n", nor);
2216 norsel = nor;
2217 srenew(orsel, nor);
2218 for (i = 0; i < nor; i++)
2220 orsel[i] = i;
2223 else
2225 /* Build the selection */
2226 norsel = 0;
2227 for (i = 0; i < j; i++)
2229 for (k = 0; k < nor; k++)
2231 if (or_label[k] == orsel[i])
2233 orsel[norsel] = k;
2234 norsel++;
2235 break;
2238 if (k == nor)
2240 fprintf(stderr, "Orientation restraint label %d not found\n",
2241 orsel[i]);
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]]);
2251 if (bORT)
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);
2261 if (bODT)
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);
2274 if (bOTEN)
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);
2286 if (bOvec)
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);
2298 else if (bDisRe)
2300 nbounds = get_bounds(ftp2fn(efTPR, NFILE, fnm), &bounds, &index, &pair, &npairs,
2301 &mtop, &top, &ir);
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);
2306 if (bDRAll)
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",
2313 ir.dr_tau);
2317 else if (bDHDL)
2319 get_dhdl_parms(ftp2fn(efTPR, NFILE, fnm), &ir);
2322 /* Initiate energies and set them to zero */
2323 edat.nsteps = 0;
2324 edat.npoints = 0;
2325 edat.nframes = 0;
2326 edat.step = NULL;
2327 edat.steps = NULL;
2328 edat.points = NULL;
2329 edat.bHaveSums = TRUE;
2330 snew(edat.s, nset);
2332 /* Initiate counters */
2333 teller = 0;
2334 teller_disre = 0;
2335 bFoundStart = FALSE;
2336 start_step = 0;
2337 start_t = 0;
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]));
2346 if (bCont)
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]);
2358 if (fr->nre > 0)
2360 /* The frame contains energies, so update cur */
2361 cur = NEXT;
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]));
2383 nfr = edat.nframes;
2384 edat.step[nfr] = fr->step;
2386 if (!bFoundStart)
2388 bFoundStart = TRUE;
2389 /* Initiate the previous step data */
2390 start_step = fr->step;
2391 start_t = fr->t;
2392 /* Initiate the energy sums */
2393 edat.steps[nfr] = 1;
2394 edat.points[nfr] = 1;
2395 for (i = 0; i < nset; i++)
2397 sss = set[i];
2398 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2399 edat.s[i].es[nfr].sum2 = 0;
2401 edat.nsteps = 1;
2402 edat.npoints = 1;
2404 else
2406 edat.steps[nfr] = fr->nsteps;
2408 if (fr->nsum <= 1)
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++)
2416 sss = set[i];
2417 edat.s[i].es[nfr].sum = fr->ener[sss].e;
2418 edat.s[i].es[nfr].sum2 = 0;
2420 edat.npoints += 1;
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++)
2429 sss = set[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;
2435 else
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)
2457 t_iatom *fa;
2458 t_iparams *ip;
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);
2478 j = fa[3*i+1];
2479 k = fa[3*i+2];
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);
2487 snew(leg, 2*nset);
2488 for (i = 0; (i < nset); i++)
2490 snew(leg[2*i], 32);
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;
2508 edat.nframes++;
2511 * Printing time, only when we do not want to skip frames
2513 if (!skip || teller % skip == 0)
2515 if (bDisRe)
2517 /*******************************************
2518 * D I S T A N C E R E S T R A I N T S
2519 *******************************************/
2520 if (ndisre > 0)
2522 GMX_RELEASE_ASSERT(blk_disre != NULL, "Trying to dereference NULL blk_disre pointer");
2523 #if !GMX_DOUBLE
2524 float *disre_rt = blk_disre->sub[0].fval;
2525 float *disre_rm3tav = blk_disre->sub[1].fval;
2526 #else
2527 double *disre_rt = blk_disre->sub[0].dval;
2528 double *disre_rm3tav = blk_disre->sub[1].dval;
2529 #endif
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);
2542 if (bDRAll)
2544 print_time(fp_pairs, fr->t);
2545 for (i = 0; (i < nset); i++)
2547 sss = set[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");
2553 teller_disre++;
2556 else if (bDHDL)
2558 do_dhdl(fr, &ir, &fp_dhdl, opt2fn("-odh", NFILE, fnm), bDp, &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas, oenv);
2561 /*******************************************
2562 * E N E R G I E S
2563 *******************************************/
2564 else
2566 if (fr->nre > 0)
2568 if (bPrAll)
2570 /* We skip frames with single points (usually only the first frame),
2571 * since they would result in an average plot with outliers.
2573 if (fr->nsum > 1)
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));
2579 fprintf(out, "\n");
2582 else
2584 print_time(out, fr->t);
2585 if (bSum)
2587 sum = 0;
2588 for (i = 0; i < nset; i++)
2590 sum += fr->ener[set[i]].e;
2592 print1(out, bDp, sum/nmol-ezero);
2594 else
2596 for (i = 0; (i < nset); i++)
2598 if (bIsEner[i])
2600 print1(out, bDp, (fr->ener[set[i]].e)/nmol-ezero);
2602 else
2604 print1(out, bDp, fr->ener[set[i]].e);
2608 fprintf(out, "\n");
2611 blk = find_block_id_enxframe(fr, enx_i, NULL);
2612 if (bORIRE && blk)
2614 #if !GMX_DOUBLE
2615 xdr_datatype dt = xdr_datatype_float;
2616 #else
2617 xdr_datatype dt = xdr_datatype_double;
2618 #endif
2619 real *vals;
2621 if ( (blk->nsub != 1) || (blk->sub[0].type != dt) )
2623 gmx_fatal(FARGS, "Orientational restraints read in incorrectly");
2625 #if !GMX_DOUBLE
2626 vals = blk->sub[0].fval;
2627 #else
2628 vals = blk->sub[0].dval;
2629 #endif
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);
2635 if (bORA || bODA)
2637 for (i = 0; i < nor; i++)
2639 orient[i] += vals[i];
2642 if (bODR)
2644 for (i = 0; i < nor; i++)
2646 odrms[i] += gmx::square(vals[i]-oobs[i]);
2649 if (bORT)
2651 fprintf(fort, " %10f", fr->t);
2652 for (i = 0; i < norsel; i++)
2654 fprintf(fort, " %g", vals[orsel[i]]);
2656 fprintf(fort, "\n");
2658 if (bODT)
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");
2667 norfr++;
2669 blk = find_block_id_enxframe(fr, enxORT, NULL);
2670 if (bOTEN && blk)
2672 #if !GMX_DOUBLE
2673 xdr_datatype dt = xdr_datatype_float;
2674 #else
2675 xdr_datatype dt = xdr_datatype_double;
2676 #endif
2677 real *vals;
2679 if ( (blk->nsub != 1) || (blk->sub[0].type != dt) )
2681 gmx_fatal(FARGS, "Orientational restraints read in incorrectly");
2683 #if !GMX_DOUBLE
2684 vals = blk->sub[0].fval;
2685 #else
2686 vals = blk->sub[0].dval;
2687 #endif
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");
2706 teller++;
2709 while (bCont && (timecheck == 0));
2711 fprintf(stderr, "\n");
2712 close_enx(fp);
2713 if (out)
2715 xvgrclose(out);
2718 if (bDRAll)
2720 xvgrclose(fp_pairs);
2723 if (bORT)
2725 xvgrclose(fort);
2727 if (bODT)
2729 xvgrclose(fodt);
2731 if (bORA)
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);
2744 xvgrclose(out);
2746 if (bODA)
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]);
2759 xvgrclose(out);
2761 if (bODR)
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));
2774 xvgrclose(out);
2776 if (bOTEN)
2778 xvgrclose(foten);
2781 if (bDisRe)
2783 analyse_disre(opt2fn("-viol", NFILE, fnm),
2784 teller_disre, violaver, bounds, index, pair, nbounds, oenv);
2786 else if (bDHDL)
2788 if (fp_dhdl)
2790 gmx_fio_fclose(fp_dhdl);
2791 printf("\n\nWrote %d lambda values with %d samples as ",
2792 dh_lambdas, dh_samples);
2793 if (dh_hists > 0)
2795 printf("%d dH histograms ", dh_hists);
2797 if (dh_blocks > 0)
2799 printf("%d dH data blocks ", dh_blocks);
2801 printf("to %s\n", opt2fn("-odh", NFILE, fnm));
2804 else
2806 gmx_fatal(FARGS, "No dH data in %s\n", opt2fn("-f", NFILE, fnm));
2810 else
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, bFluct,
2815 bVisco, opt2fn("-vis", NFILE, fnm),
2816 nmol,
2817 start_step, start_t, frame[cur].step, frame[cur].t,
2818 reftemp, &edat,
2819 nset, set, bIsEner, leg, enm, Vaver, ezero, nbmin, nbmax,
2820 oenv);
2821 if (bFluctProps)
2823 calc_fluctuation_props(stdout, bDriftCorr, dt, nset, nmol, leg, &edat,
2824 nbmin, nbmax);
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);
2847 return 0;