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,2017 by the GROMACS development team.
7 * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
8 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9 * and including many others, as listed in the AUTHORS file in the
10 * top-level source directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
47 #include "gromacs/commandline/pargs.h"
48 #include "gromacs/fileio/matio.h"
49 #include "gromacs/fileio/pdbio.h"
50 #include "gromacs/fileio/xvgr.h"
51 #include "gromacs/gmxana/gmx_ana.h"
52 #include "gromacs/gmxana/gstat.h"
53 #include "gromacs/math/functions.h"
54 #include "gromacs/math/units.h"
55 #include "gromacs/math/vec.h"
56 #include "gromacs/topology/topology.h"
57 #include "gromacs/utility/arraysize.h"
58 #include "gromacs/utility/fatalerror.h"
59 #include "gromacs/utility/futil.h"
60 #include "gromacs/utility/smalloc.h"
63 static int index2(const int* ibox, int x, int y)
65 return (ibox[1] * x + y);
68 static int index3(const int* ibox, int x, int y, int z)
70 return (ibox[2] * (ibox[1] * x + y) + z);
73 static int64_t indexn(int ndim, const int* ibox, const int* nxyz)
78 /* Compute index in 1-D array */
80 for (k = 0; (k < ndim); k++)
83 for (kk = k + 1; (kk < ndim); kk++)
94 int Nx; /* x grid points in unit cell */
95 int Ny; /* y grid points in unit cell */
96 int Nz; /* z grid points in unit cell */
97 int dmin[3]; /* starting point x,y,z*/
98 int dmax[3]; /* ending point x,y,z */
99 real cell[6]; /* usual cell parameters */
103 static void lo_write_xplor(XplorMap* map, const char* file)
108 fp = gmx_ffopen(file, "w");
109 /* The REMARKS part is the worst part of the XPLOR format
110 * and may cause problems with some programs
112 fprintf(fp, "\n 2 !NTITLE\n");
113 fprintf(fp, " REMARKS Energy Landscape from GROMACS\n");
114 fprintf(fp, " REMARKS DATE: 2004-12-21 \n");
116 " %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
127 "%12.5E%12.5E%12.5E%12.5E%12.5E%12.5E\n",
134 fprintf(fp, "ZYX\n");
137 for (n = 0; n < map->Nz; n++, z++)
139 fprintf(fp, "%8d\n", z);
140 for (i = 0; i < map->Nx * map->Ny; i += 6)
142 for (j = 0; j < 6; j++)
144 if (i + j < map->Nx * map->Ny)
146 fprintf(fp, "%12.5E", map->ed[n * map->Nx * map->Ny + i + j]);
152 fprintf(fp, " -9999\n");
156 static void write_xplor(const char* file, const real* data, int* ibox, const real dmin[], const real dmax[])
165 snew(xm->ed, xm->Nx * xm->Ny * xm->Nz);
167 for (k = 0; (k < xm->Nz); k++)
169 for (j = 0; (j < xm->Ny); j++)
171 for (i = 0; (i < xm->Nx); i++)
173 xm->ed[n++] = data[index3(ibox, i, j, k)];
177 xm->cell[0] = dmax[XX] - dmin[XX];
178 xm->cell[1] = dmax[YY] - dmin[YY];
179 xm->cell[2] = dmax[ZZ] - dmin[ZZ];
180 xm->cell[3] = xm->cell[4] = xm->cell[5] = 90;
182 clear_ivec(xm->dmin);
183 xm->dmax[XX] = ibox[XX] - 1;
184 xm->dmax[YY] = ibox[YY] - 1;
185 xm->dmax[ZZ] = ibox[ZZ] - 1;
187 lo_write_xplor(xm, file);
193 static void normalize_p_e(int len, double* P, const int* nbin, real* E, real pmin)
198 for (i = 0; (i < len); i++)
203 E[i] = E[i] / nbin[i];
206 printf("Ptot = %g\n", Ptot);
207 for (i = 0; (i < len); i++)
210 /* Have to check for pmin after normalizing to prevent "stretching"
226 static int comp_minima(const void* a, const void* b)
228 const t_minimum* ma = reinterpret_cast<const t_minimum*>(a);
229 const t_minimum* mb = reinterpret_cast<const t_minimum*>(b);
232 if (ma->ener < mb->ener)
236 else if (ma->ener > mb->ener)
246 static inline void print_minimum(FILE* fp, int num, const t_minimum* min)
249 "Minimum %d at index "
250 "%" PRId64 " energy %10.3f\n",
256 static inline void add_minimum(FILE* fp, int num, const t_minimum* min, t_minimum* mm)
258 print_minimum(fp, num, min);
259 mm[num].index = min->index;
260 mm[num].ener = min->ener;
263 static inline gmx_bool is_local_minimum_from_below(const t_minimum* this_min,
269 return ((dimension_index == dimension_min)
270 || ((dimension_index > dimension_min) && (this_min->ener < W[neighbour_index])));
271 /* Note over/underflow within W cannot occur. */
274 static inline gmx_bool is_local_minimum_from_above(const t_minimum* this_min,
280 return ((dimension_index == dimension_max)
281 || ((dimension_index < dimension_max) && (this_min->ener < W[neighbour_index])));
282 /* Note over/underflow within W cannot occur. */
285 static void pick_minima(const char* logfile, int* ibox, int ndim, int len, real W[])
289 t_minimum *mm, this_min;
291 int loopmax, loopcounter;
295 fp = gmx_ffopen(logfile, "w");
296 /* Loop over each element in the array of dimenion ndim seeking
297 * minima with respect to every dimension. Specialized loops for
298 * speed with ndim == 2 and ndim == 3. */
302 /* This is probably impossible to reach anyway. */
305 for (i = 0; (i < ibox[0]); i++)
307 for (j = 0; (j < ibox[1]); j++)
309 /* Get the index of this point in the flat array */
310 this_min.index = index2(ibox, i, j);
311 this_min.ener = W[this_min.index];
312 if (is_local_minimum_from_below(&this_min, i, 0, index2(ibox, i - 1, j), W)
313 && is_local_minimum_from_above(&this_min, i, ibox[0] - 1, index2(ibox, i + 1, j), W)
314 && is_local_minimum_from_below(&this_min, j, 0, index2(ibox, i, j - 1), W)
315 && is_local_minimum_from_above(&this_min, j, ibox[1] - 1, index2(ibox, i, j + 1), W))
317 add_minimum(fp, nmin, &this_min, mm);
324 for (i = 0; (i < ibox[0]); i++)
326 for (j = 0; (j < ibox[1]); j++)
328 for (k = 0; (k < ibox[2]); k++)
330 /* Get the index of this point in the flat array */
331 this_min.index = index3(ibox, i, j, k);
332 this_min.ener = W[this_min.index];
333 if (is_local_minimum_from_below(&this_min, i, 0, index3(ibox, i - 1, j, k), W)
334 && is_local_minimum_from_above(
335 &this_min, i, ibox[0] - 1, index3(ibox, i + 1, j, k), W)
336 && is_local_minimum_from_below(&this_min, j, 0, index3(ibox, i, j - 1, k), W)
337 && is_local_minimum_from_above(
338 &this_min, j, ibox[1] - 1, index3(ibox, i, j + 1, k), W)
339 && is_local_minimum_from_below(&this_min, k, 0, index3(ibox, i, j, k - 1), W)
340 && is_local_minimum_from_above(
341 &this_min, k, ibox[2] - 1, index3(ibox, i, j, k + 1), W))
343 add_minimum(fp, nmin, &this_min, mm);
351 /* Note this treats ndim == 1 and ndim > 3 */
353 /* Set up an ndim-dimensional vector to loop over the points
354 * on the grid. (0,0,0, ... 0) is an acceptable place to
356 snew(this_point, ndim);
358 /* Determine the number of points of the ndim-dimensional
361 for (i = 1; i < ndim; i++)
367 while (loopmax > loopcounter)
369 gmx_bool bMin = TRUE;
371 /* Get the index of this_point in the flat array */
372 this_min.index = indexn(ndim, ibox, this_point);
373 this_min.ener = W[this_min.index];
375 /* Is this_point a minimum from above and below in each
377 for (i = 0; bMin && (i < ndim); i++)
379 /* Save the index of this_point within the curent
380 * dimension so we can change that index in the
381 * this_point array for use with indexn(). */
382 int index = this_point[i];
385 && is_local_minimum_from_below(
386 &this_min, index, 0, indexn(ndim, ibox, this_point), W);
389 && is_local_minimum_from_above(
390 &this_min, index, ibox[i] - 1, indexn(ndim, ibox, this_point), W);
395 add_minimum(fp, nmin, &this_min, mm);
399 /* update global loop counter */
402 /* Avoid underflow of this_point[i] */
403 if (loopmax > loopcounter)
405 /* update this_point non-recursively */
408 while (ibox[i] == this_point[i])
412 /* this_point[i] cannot underflow because
413 * loopmax > loopcounter. */
422 qsort(mm, nmin, sizeof(mm[0]), comp_minima);
423 fprintf(fp, "Minima sorted after energy\n");
424 for (i = 0; (i < nmin); i++)
426 print_minimum(fp, i, &mm[i]);
432 static void do_sham(const char* fn,
461 real * min_eig, *max_eig;
462 real * axis_x, *axis_y, *axis_z, *axis = nullptr;
464 real ** PP, *W, *E, **WW, **EE, *S, **SS, *M, *bE;
467 double * bfac, efac, bref, Pmax, Wmin, Wmax, Winf, Emin, Emax, Einf, Smin, Smax, Sinf;
469 int i, j, k, imin, len, index, *nbin, *bindex, bi;
474 t_rgb rlo = { 0, 0, 0 };
475 t_rgb rhi = { 1, 1, 1 };
477 /* Determine extremes for the eigenvectors */
484 for (i = 0; (i < neig); i++)
486 /* Check for input constraints */
487 min_eig[i] = max_eig[i] = eig[i][0];
488 for (j = 0; (j < n); j++)
490 min_eig[i] = std::min(min_eig[i], eig[i][j]);
491 max_eig[i] = std::max(max_eig[i], eig[i][j]);
492 delta[i] = (max_eig[i] - min_eig[i]) / (2.0 * ibox[i]);
494 /* Add some extra space, half a bin on each side, unless the
495 * user has set the limits.
499 if (max_eig[i] > xmax[i])
501 gmx_warning("Your xmax[%d] value %f is smaller than the largest data point %f",
506 max_eig[i] = xmax[i];
510 max_eig[i] += delta[i];
515 if (min_eig[i] < xmin[i])
517 gmx_warning("Your xmin[%d] value %f is larger than the smallest data point %f",
522 min_eig[i] = xmin[i];
526 min_eig[i] -= delta[i];
528 bfac[i] = ibox[i] / (max_eig[i] - min_eig[i]);
531 bref = 1 / (BOLTZ * Tref);
533 if (bGE || nenerT == 2)
537 for (j = 0; (j < n); j++)
541 bE[j] = bref * enerT[0][j];
545 bE[j] = (bref - 1 / (BOLTZ * enerT[1][j])) * enerT[0][j];
547 Emin = std::min(Emin, static_cast<double>(bE[j]));
555 for (i = 0; (i < neig); i++)
559 printf("There are %d bins in the %d-dimensional histogram. Beta-Emin = %g\n", len, neig, Emin);
569 /* Loop over projections */
570 for (j = 0; (j < n); j++)
572 /* Loop over dimensions */
574 for (i = 0; (i < neig); i++)
576 nxyz[i] = static_cast<int>(bfac[i] * (eig[i][j] - min_eig[i]));
577 if (nxyz[i] < 0 || nxyz[i] >= ibox[i])
584 index = indexn(neig, ibox, nxyz);
585 range_check(index, 0, len);
586 /* Compute the exponential factor */
589 efac = std::exp(-bE[j] + Emin);
595 /* Apply the bin volume correction for a multi-dimensional distance */
596 for (i = 0; i < neig; i++)
602 else if (idim[i] == 3)
604 efac /= gmx::square(eig[i][j]);
606 else if (idim[i] == -1)
608 efac /= std::sin(DEG2RAD * eig[i][j]);
611 /* Update the probability */
613 /* Update the energy */
616 E[index] += enerT[0][j];
618 /* Statistics: which "structure" in which bin */
623 /* Normalize probability */
624 normalize_p_e(len, P, nbin, E, pmin);
626 /* Compute boundaries for the Free energy */
630 /* Recompute Emin: it may have changed due to averaging */
633 for (i = 0; (i < len); i++)
637 Pmax = std::max(P[i], Pmax);
638 W[i] = -BOLTZ * Tref * std::log(P[i]);
644 Emin = std::min(static_cast<double>(E[i]), Emin);
645 Emax = std::max(static_cast<double>(E[i]), Emax);
646 Wmax = std::max(static_cast<double>(W[i]), Wmax);
666 /* Write out the free energy as a function of bin index */
667 fp = gmx_ffopen(fn, "w");
668 for (i = 0; (i < len); i++)
673 S[i] = E[i] - W[i] - Smin;
674 fprintf(fp, "%5d %10.5e %10.5e %10.5e\n", i, W[i], E[i], S[i]);
684 /* Organize the structures in the bins */
686 snew(b->index, len + 1);
689 for (i = 0; (i < len); i++)
691 b->index[i + 1] = b->index[i] + nbin[i];
694 for (i = 0; (i < n); i++)
697 b->a[b->index[bi] + nbin[bi]] = i;
700 /* Consistency check */
701 /* This no longer applies when we allow the plot to be smaller
702 than the sampled space.
703 for(i=0; (i<len); i++) {
704 if (nbin[i] != (b->index[i+1] - b->index[i]))
705 gmx_fatal(FARGS,"nbin[%d] = %d, should be %d",i,nbin[i],
706 b->index[i+1] - b->index[i]);
709 /* Write the index file */
710 fp = gmx_ffopen(ndx, "w");
711 for (i = 0; (i < len); i++)
715 fprintf(fp, "[ %d ]\n", i);
716 for (j = b->index[i]; (j < b->index[i + 1]); j++)
718 fprintf(fp, "%d\n", b->a[j] + 1);
723 snew(axis_x, ibox[0] + 1);
724 snew(axis_y, ibox[1] + 1);
725 snew(axis_z, ibox[2] + 1);
726 maxbox = std::max(ibox[0], std::max(ibox[1], ibox[2]));
727 snew(PP, maxbox * maxbox);
728 snew(WW, maxbox * maxbox);
729 snew(EE, maxbox * maxbox);
730 snew(SS, maxbox * maxbox);
731 for (i = 0; (i < std::min(neig, 3)); i++)
735 case 0: axis = axis_x; break;
736 case 1: axis = axis_y; break;
737 case 2: axis = axis_z; break;
740 for (j = 0; j <= ibox[i]; j++)
742 axis[j] = min_eig[i] + j / bfac[i];
746 pick_minima(logf, ibox, neig, len, W);
751 flags = MAT_SPATIAL_X | MAT_SPATIAL_Y;
754 /* Dump to XPM file */
756 for (i = 0; (i < ibox[0]); i++)
758 snew(PP[i], ibox[1]);
759 for (j = 0; j < ibox[1]; j++)
761 PP[i][j] = P[i * ibox[1] + j];
763 WW[i] = &(W[i * ibox[1]]);
764 EE[i] = &(E[i * ibox[1]]);
765 SS[i] = &(S[i * ibox[1]]);
767 fp = gmx_ffopen(xpmP, "w");
770 "Probability Distribution",
785 fp = gmx_ffopen(xpm, "w");
788 "Gibbs Energy Landscape",
803 fp = gmx_ffopen(xpm2, "w");
806 "Enthalpy Landscape",
821 fp = gmx_ffopen(xpm3, "w");
842 /* Dump to PDB file */
843 fp = gmx_ffopen(pdb, "w");
844 for (i = 0; (i < ibox[0]); i++)
846 xxx[XX] = 3 * i + 1.5 * (1 - ibox[0]);
847 for (j = 0; (j < ibox[1]); j++)
849 xxx[YY] = 3 * j + 1.5 * (1 - ibox[1]);
850 for (k = 0; (k < ibox[2]); k++)
852 xxx[ZZ] = 3 * k + 1.5 * (1 - ibox[2]);
853 index = index3(ibox, i, j, k);
857 "%-6s%5d %-4.4s%3.3s %4d %8.3f%8.3f%8.3f%6.2f%6.2f\n",
873 write_xplor("out.xplor", W, ibox, min_eig, max_eig);
874 nxyz[XX] = imin / (ibox[1] * ibox[2]);
875 nxyz[YY] = (imin - nxyz[XX] * ibox[1] * ibox[2]) / ibox[2];
876 nxyz[ZZ] = imin % ibox[2];
877 for (i = 0; (i < ibox[0]); i++)
880 for (j = 0; (j < ibox[1]); j++)
882 WW[i][j] = W[index3(ibox, i, j, nxyz[ZZ])];
885 snew(buf, std::strlen(xpm) + 4);
886 sprintf(buf, "%s", xpm);
887 sprintf(&buf[std::strlen(xpm) - 4], "12.xpm");
888 fp = gmx_ffopen(buf, "w");
891 "Gibbs Energy Landscape",
906 for (i = 0; (i < ibox[0]); i++)
908 for (j = 0; (j < ibox[2]); j++)
910 WW[i][j] = W[index3(ibox, i, nxyz[YY], j)];
913 sprintf(&buf[std::strlen(xpm) - 4], "13.xpm");
914 fp = gmx_ffopen(buf, "w");
917 "SHAM Energy Landscape",
932 for (i = 0; (i < ibox[1]); i++)
934 for (j = 0; (j < ibox[2]); j++)
936 WW[i][j] = W[index3(ibox, nxyz[XX], i, j)];
939 sprintf(&buf[std::strlen(xpm) - 4], "23.xpm");
940 fp = gmx_ffopen(buf, "w");
943 "SHAM Energy Landscape",
962 static void ehisto(const char* fh, int n, real** enerT, const gmx_output_env_t* oenv)
965 int i, j, k, nbin, blength;
967 real *T, bmin, bmax, bwidth;
975 for (j = 1; (j < n); j++)
977 for (k = 0; (k < nbin); k++)
979 if (T[k] == enerT[1][j])
988 T[nbin] = enerT[1][j];
991 bmin = std::min(enerT[0][j], bmin);
992 bmax = std::max(enerT[0][j], bmax);
995 blength = static_cast<int>((bmax - bmin) / bwidth + 2);
997 for (i = 0; (i < nbin); i++)
999 snew(histo[i], blength);
1001 for (j = 0; (j < n); j++)
1003 k = static_cast<int>((enerT[0][j] - bmin) / bwidth);
1004 histo[bindex[j]][k]++;
1006 fp = xvgropen(fh, "Energy distribution", "E (kJ/mol)", "", oenv);
1007 for (j = 0; (j < blength); j++)
1009 fprintf(fp, "%8.3f", bmin + j * bwidth);
1010 for (k = 0; (k < nbin); k++)
1012 fprintf(fp, " %6d", histo[k][j]);
1019 int gmx_sham(int argc, char* argv[])
1021 const char* desc[] = {
1022 "[THISMODULE] makes multi-dimensional free-energy, enthalpy and entropy plots.",
1023 "[THISMODULE] reads one or more [REF].xvg[ref] files and analyzes data sets.",
1024 "The basic purpose of [THISMODULE] is to plot Gibbs free energy landscapes",
1025 "(option [TT]-ls[tt])",
1026 "by Bolzmann inverting multi-dimensional histograms (option [TT]-lp[tt]),",
1028 "make enthalpy (option [TT]-lsh[tt]) and entropy (option [TT]-lss[tt])",
1029 "plots. The histograms can be made for any quantities the user supplies.",
1030 "A line in the input file may start with a time",
1031 "(see option [TT]-time[tt]) and any number of [IT]y[it]-values may follow.",
1032 "Multiple sets can also be",
1033 "read when they are separated by & (option [TT]-n[tt]),",
1034 "in this case only one [IT]y[it]-value is read from each line.",
1035 "All lines starting with # and @ are skipped.",
1037 "Option [TT]-ge[tt] can be used to supply a file with free energies",
1038 "when the ensemble is not a Boltzmann ensemble, but needs to be biased",
1039 "by this free energy. One free energy value is required for each",
1040 "(multi-dimensional) data point in the [TT]-f[tt] input.",
1042 "Option [TT]-ene[tt] can be used to supply a file with energies.",
1043 "These energies are used as a weighting function in the single",
1044 "histogram analysis method by Kumar et al. When temperatures",
1045 "are supplied (as a second column in the file), an experimental",
1046 "weighting scheme is applied. In addition the vales",
1047 "are used for making enthalpy and entropy plots.",
1049 "With option [TT]-dim[tt], dimensions can be gives for distances.",
1050 "When a distance is 2- or 3-dimensional, the circumference or surface",
1051 "sampled by two particles increases with increasing distance.",
1052 "Depending on what one would like to show, one can choose to correct",
1053 "the histogram and free-energy for this volume effect.",
1054 "The probability is normalized by r and r^2 for dimensions of 2 and 3, ",
1056 "A value of -1 is used to indicate an angle in degrees between two",
1057 "vectors: a sin(angle) normalization will be applied.",
1058 "[BB]Note[bb] that for angles between vectors the inner-product or cosine",
1059 "is the natural quantity to use, as it will produce bins of the same",
1062 static real tb = -1, te = -1;
1063 static gmx_bool bHaveT = TRUE, bDer = FALSE;
1064 static gmx_bool bSham = TRUE;
1065 static real Tref = 298.15, pmin = 0, ttol = 0, pmax = 0, gmax = 0, emin = 0, emax = 0;
1066 static rvec nrdim = { 1, 1, 1 };
1067 static rvec nrbox = { 32, 32, 32 };
1068 static rvec xmin = { 0, 0, 0 }, xmax = { 1, 1, 1 };
1069 static int nsets_in = 1, nlevels = 25;
1071 { "-time", FALSE, etBOOL, { &bHaveT }, "Expect a time in the input" },
1072 { "-b", FALSE, etREAL, { &tb }, "First time to read from set" },
1073 { "-e", FALSE, etREAL, { &te }, "Last time to read from set" },
1074 { "-ttol", FALSE, etREAL, { &ttol }, "Tolerance on time in appropriate units (usually ps)" },
1079 "Read this number of sets separated by lines containing only an ampersand" },
1080 { "-d", FALSE, etBOOL, { &bDer }, "Use the derivative" },
1085 "Turn off energy weighting even if energies are given" },
1086 { "-tsham", FALSE, etREAL, { &Tref }, "Temperature for single histogram analysis" },
1091 "Minimum probability. Anything lower than this will be set to zero" },
1096 "Dimensions for distances, used for volume correction (max 3 values, dimensions > 3 will "
1097 "get the same value as the last)" },
1102 "Number of bins for energy landscapes (max 3 values, dimensions > 3 will get the same "
1103 "value as the last)" },
1108 "Minimum for the axes in energy landscape (see above for > 3 dimensions)" },
1113 "Maximum for the axes in energy landscape (see above for > 3 dimensions)" },
1114 { "-pmax", FALSE, etREAL, { &pmax }, "Maximum probability in output, default is calculate" },
1115 { "-gmax", FALSE, etREAL, { &gmax }, "Maximum free energy in output, default is calculate" },
1116 { "-emin", FALSE, etREAL, { &emin }, "Minimum enthalpy in output, default is calculate" },
1117 { "-emax", FALSE, etREAL, { &emax }, "Maximum enthalpy in output, default is calculate" },
1118 { "-nlevels", FALSE, etINT, { &nlevels }, "Number of levels for energy landscape" },
1120 #define NPA asize(pa)
1122 int n, e_n, nset, e_nset = 0, i, *idim, *ibox;
1123 real ** val, **et_val, *t, *e_t, e_dt, dt;
1125 const char * fn_ge, *fn_ene;
1126 gmx_output_env_t* oenv;
1127 int64_t num_grid_points;
1130 { efXVG, "-f", "graph", ffREAD }, { efXVG, "-ge", "gibbs", ffOPTRD },
1131 { efXVG, "-ene", "esham", ffOPTRD }, { efXVG, "-dist", "ener", ffOPTWR },
1132 { efXVG, "-histo", "edist", ffOPTWR }, { efNDX, "-bin", "bindex", ffOPTWR },
1133 { efXPM, "-lp", "prob", ffOPTWR }, { efXPM, "-ls", "gibbs", ffOPTWR },
1134 { efXPM, "-lsh", "enthalpy", ffOPTWR }, { efXPM, "-lss", "entropy", ffOPTWR },
1135 { efPDB, "-ls3", "gibbs3", ffOPTWR }, { efLOG, "-g", "shamlog", ffOPTWR }
1137 #define NFILE asize(fnm)
1142 if (!parse_common_args(
1143 &argc, argv, PCA_CAN_VIEW, NFILE, fnm, npargs, pa, asize(desc), desc, 0, nullptr, &oenv))
1148 val = read_xvg_time(opt2fn("-f", NFILE, fnm),
1150 opt2parg_bSet("-b", npargs, pa),
1152 opt2parg_bSet("-e", npargs, pa),
1159 printf("Read %d sets of %d points, dt = %g\n\n", nset, n, dt);
1161 fn_ge = opt2fn_null("-ge", NFILE, fnm);
1162 fn_ene = opt2fn_null("-ene", NFILE, fnm);
1164 if (fn_ge && fn_ene)
1166 gmx_fatal(FARGS, "Can not do free energy and energy corrections at the same time");
1169 if (fn_ge || fn_ene)
1171 et_val = read_xvg_time(fn_ge ? fn_ge : fn_ene,
1173 opt2parg_bSet("-b", npargs, pa),
1175 opt2parg_bSet("-e", npargs, pa),
1186 gmx_fatal(FARGS, "Can only handle one free energy component in %s", fn_ge);
1191 if (e_nset != 1 && e_nset != 2)
1194 "Can only handle one energy component or one energy and one T in %s",
1201 "Number of energies (%d) does not match number of entries (%d) in %s",
1204 opt2fn("-f", NFILE, fnm));
1212 if (fn_ene && et_val)
1214 ehisto(opt2fn("-histo", NFILE, fnm), e_n, et_val, oenv);
1217 snew(idim, std::max(3, nset));
1218 snew(ibox, std::max(3, nset));
1219 snew(rmin, std::max(3, nset));
1220 snew(rmax, std::max(3, nset));
1221 for (i = 0; (i < std::min(3, nset)); i++)
1223 idim[i] = static_cast<int>(nrdim[i]);
1224 ibox[i] = static_cast<int>(nrbox[i]);
1228 for (; (i < nset); i++)
1230 idim[i] = static_cast<int>(nrdim[2]);
1231 ibox[i] = static_cast<int>(nrbox[2]);
1236 /* Check that the grid size is manageable. */
1237 num_grid_points = ibox[0];
1238 for (i = 1; i < nset; i++)
1241 if (!check_int_multiply_for_overflow(num_grid_points, ibox[i], &result))
1244 "The number of dimensions and grid points is too large for this tool.\n");
1246 num_grid_points = result;
1248 /* The number of grid points fits in a int64_t. */
1250 do_sham(opt2fn("-dist", NFILE, fnm),
1251 opt2fn("-bin", NFILE, fnm),
1252 opt2fn("-lp", NFILE, fnm),
1253 opt2fn("-ls", NFILE, fnm),
1254 opt2fn("-lsh", NFILE, fnm),
1255 opt2fn("-lss", NFILE, fnm),
1256 opt2fn("-ls3", NFILE, fnm),
1257 opt2fn("-g", NFILE, fnm),
1267 opt2parg_bSet("-emin", NPA, pa) ? &emin : nullptr,
1268 opt2parg_bSet("-emax", NPA, pa) ? &emax : nullptr,
1273 opt2parg_bSet("-xmin", NPA, pa),
1275 opt2parg_bSet("-xmax", NPA, pa),