3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Green Red Orange Magenta Azure Cyan Skyblue
43 #include "gmx_fatal.h"
58 static int search_str2(int nstr, char **str, char *key)
61 int keylen = strlen(key);
64 while ( (n < keylen) && ((key[n] < '0') || (key[n] > '9')) )
68 for (i = 0; (i < nstr); i++)
70 if (gmx_strncasecmp(str[i], key, n) == 0)
79 int gmx_enemat(int argc, char *argv[])
81 const char *desc[] = {
82 "[TT]g_enemat[tt] extracts an energy matrix from the energy file ([TT]-f[tt]).",
83 "With [TT]-groups[tt] a file must be supplied with on each",
84 "line a group of atoms to be used. For these groups matrix of",
85 "interaction energies will be extracted from the energy file",
86 "by looking for energy groups with names corresponding to pairs",
87 "of groups of atoms, e.g. if your [TT]-groups[tt] file contains:[BR]",
89 "[TT]Protein[tt][BR]",
91 "then energy groups with names like 'Coul-SR:Protein-SOL' and ",
92 "'LJ:Protein-SOL' are expected in the energy file (although",
93 "[TT]g_enemat[tt] is most useful if many groups are analyzed",
94 "simultaneously). Matrices for different energy types are written",
95 "out separately, as controlled by the",
96 "[TT]-[no]coul[tt], [TT]-[no]coulr[tt], [TT]-[no]coul14[tt], ",
97 "[TT]-[no]lj[tt], [TT]-[no]lj14[tt], ",
98 "[TT]-[no]bham[tt] and [TT]-[no]free[tt] options.",
99 "Finally, the total interaction energy energy per group can be ",
100 "calculated ([TT]-etot[tt]).[PAR]",
102 "An approximation of the free energy can be calculated using:",
103 "[MATH]E[SUB]free[sub] = E[SUB]0[sub] + kT [LOG][CHEVRON][EXP](E-E[SUB]0[sub])/kT[exp][chevron][log][math], where '[MATH][CHEVRON][chevron][math]'",
104 "stands for time-average. A file with reference free energies",
105 "can be supplied to calculate the free energy difference",
106 "with some reference state. Group names (e.g. residue names)",
107 "in the reference file should correspond to the group names",
108 "as used in the [TT]-groups[tt] file, but a appended number",
109 "(e.g. residue number) in the [TT]-groups[tt] will be ignored",
112 static gmx_bool bSum = FALSE;
113 static gmx_bool bMeanEmtx = TRUE;
114 static int skip = 0, nlevels = 20;
115 static real cutmax = 1e20, cutmin = -1e20, reftemp = 300.0;
116 static gmx_bool bCoulSR = TRUE, bCoulLR = FALSE, bCoul14 = FALSE;
117 static gmx_bool bLJSR = TRUE, bLJLR = FALSE, bLJ14 = FALSE, bBhamSR = FALSE, bBhamLR = FALSE,
120 { "-sum", FALSE, etBOOL, {&bSum},
121 "Sum the energy terms selected rather than display them all" },
122 { "-skip", FALSE, etINT, {&skip},
123 "Skip number of frames between data points" },
124 { "-mean", FALSE, etBOOL, {&bMeanEmtx},
125 "with [TT]-groups[tt] extracts matrix of mean energies instead of "
126 "matrix for each timestep" },
127 { "-nlevels", FALSE, etINT, {&nlevels}, "number of levels for matrix colors"},
128 { "-max", FALSE, etREAL, {&cutmax}, "max value for energies"},
129 { "-min", FALSE, etREAL, {&cutmin}, "min value for energies"},
130 { "-coulsr", FALSE, etBOOL, {&bCoulSR}, "extract Coulomb SR energies"},
131 { "-coullr", FALSE, etBOOL, {&bCoulLR}, "extract Coulomb LR energies"},
132 { "-coul14", FALSE, etBOOL, {&bCoul14}, "extract Coulomb 1-4 energies"},
133 { "-ljsr", FALSE, etBOOL, {&bLJSR}, "extract Lennard-Jones SR energies"},
134 { "-ljlr", FALSE, etBOOL, {&bLJLR}, "extract Lennard-Jones LR energies"},
135 { "-lj14", FALSE, etBOOL, {&bLJ14}, "extract Lennard-Jones 1-4 energies"},
136 { "-bhamsr", FALSE, etBOOL, {&bBhamSR}, "extract Buckingham SR energies"},
137 { "-bhamlr", FALSE, etBOOL, {&bBhamLR}, "extract Buckingham LR energies"},
138 { "-free", FALSE, etBOOL, {&bFree}, "calculate free energy"},
139 { "-temp", FALSE, etREAL, {&reftemp},
140 "reference temperature for free energy calculation"}
142 /* We will define egSP more energy-groups:
143 egTotal (total energy) */
146 gmx_bool egrp_use[egNR+egSP];
150 gmx_enxnm_t *enm = NULL;
154 gmx_bool bCont, bRef;
155 gmx_bool bCutmax, bCutmin;
156 real **eneset, *time = NULL;
157 int *set, i, j, k, prevk, m = 0, n, nre, nset, nenergy;
158 char **groups = NULL;
159 char groupname[255], fn[255];
161 t_rgb rlo, rhi, rmid;
162 real emax, emid, emin;
163 real ***emat, **etot, *groupnr;
164 double beta, expE, **e, *eaver, *efree = NULL, edum;
166 char **ereflines, **erefres = NULL;
167 real *eref = NULL, *edif = NULL;
172 { efEDR, "-f", NULL, ffOPTRD },
173 { efDAT, "-groups", "groups.dat", ffREAD },
174 { efDAT, "-eref", "eref.dat", ffOPTRD },
175 { efXPM, "-emat", "emat", ffWRITE },
176 { efXVG, "-etot", "energy", ffWRITE }
178 #define NFILE asize(fnm)
180 parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
181 NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv);
183 egrp_use[egCOULSR] = bCoulSR;
184 egrp_use[egLJSR] = bLJSR;
185 egrp_use[egBHAMSR] = bBhamSR;
186 egrp_use[egCOULLR] = bCoulLR;
187 egrp_use[egLJLR] = bLJLR;
188 egrp_use[egBHAMLR] = bBhamLR;
189 egrp_use[egCOUL14] = bCoul14;
190 egrp_use[egLJ14] = bLJ14;
191 egrp_use[egTotal] = TRUE;
193 bRef = opt2bSet("-eref", NFILE, fnm);
194 in = open_enx(ftp2fn(efEDR, NFILE, fnm), "r");
195 do_enxnms(in, &nre, &enm);
199 gmx_fatal(FARGS, "No energies!\n");
202 bCutmax = opt2parg_bSet("-max", asize(pa), pa);
203 bCutmin = opt2parg_bSet("-min", asize(pa), pa);
207 /* Read groupnames from input file and construct selection of
208 energy groups from it*/
210 fprintf(stderr, "Will read groupnames from inputfile\n");
211 ngroups = get_lines(opt2fn("-groups", NFILE, fnm), &groups);
212 fprintf(stderr, "Read %d groups\n", ngroups);
213 snew(set, sqr(ngroups)*egNR/2);
216 for (i = 0; (i < ngroups); i++)
218 fprintf(stderr, "\rgroup %d", i);
219 for (j = i; (j < ngroups); j++)
221 for (m = 0; (m < egNR); m++)
225 sprintf(groupname, "%s:%s-%s", egrp_nm[m], groups[i], groups[j]);
227 fprintf(stderr, "\r%-15s %5d", groupname, n);
229 for (k = prevk; (k < prevk+nre); k++)
231 if (strcmp(enm[k%nre].name, groupname) == 0)
239 fprintf(stderr, "WARNING! could not find group %s (%d,%d)"
240 "in energy file\n", groupname, i, j);
250 fprintf(stderr, "\n");
252 snew(eneset, nset+1);
253 fprintf(stderr, "Will select half-matrix of energies with %d elements\n", n);
255 /* Start reading energy frames */
261 bCont = do_enx(in, fr);
264 timecheck = check_times(fr->t);
267 while (bCont && (timecheck < 0));
271 #define DONTSKIP(cnt) (skip) ? ((cnt % skip) == 0) : TRUE
275 fprintf(stderr, "\rRead frame: %d, Time: %.3f", teller, fr->t);
277 if ((nenergy % 1000) == 0)
279 srenew(time, nenergy+1000);
280 for (i = 0; (i <= nset); i++)
282 srenew(eneset[i], nenergy+1000);
285 time[nenergy] = fr->t;
287 for (i = 0; (i < nset); i++)
289 eneset[i][nenergy] = fr->ener[set[i]].e;
290 sum += fr->ener[set[i]].e;
294 eneset[nset][nenergy] = sum;
301 while (bCont && (timecheck == 0));
303 fprintf(stderr, "\n");
305 fprintf(stderr, "Will build energy half-matrix of %d groups, %d elements, "
306 "over %d frames\n", ngroups, nset, nenergy);
308 snew(emat, egNR+egSP);
309 for (j = 0; (j < egNR+egSP); j++)
313 snew(emat[j], ngroups);
314 for (i = 0; (i < ngroups); i++)
316 snew(emat[j][i], ngroups);
320 snew(groupnr, ngroups);
321 for (i = 0; (i < ngroups); i++)
325 rlo.r = 1.0, rlo.g = 0.0, rlo.b = 0.0;
326 rmid.r = 1.0, rmid.g = 1.0, rmid.b = 1.0;
327 rhi.r = 0.0, rhi.g = 0.0, rhi.b = 1.0;
331 for (i = 0; (i < ngroups); i++)
336 for (i = 0; (i < ngroups); i++)
338 for (j = i; (j < ngroups); j++)
340 for (m = 0; (m < egNR); m++)
344 for (k = 0; (k < nenergy); k++)
346 emat[m][i][j] += eneset[n][k];
347 e[i][k] += eneset[n][k]; /* *0.5; */
348 e[j][k] += eneset[n][k]; /* *0.5; */
351 emat[egTotal][i][j] += emat[m][i][j];
352 emat[m][i][j] /= nenergy;
353 emat[m][j][i] = emat[m][i][j];
356 emat[egTotal][i][j] /= nenergy;
357 emat[egTotal][j][i] = emat[egTotal][i][j];
364 fprintf(stderr, "Will read reference energies from inputfile\n");
365 neref = get_lines(opt2fn("-eref", NFILE, fnm), &ereflines);
366 fprintf(stderr, "Read %d reference energies\n", neref);
368 snew(erefres, neref);
369 for (i = 0; (i < neref); i++)
372 sscanf(ereflines[i], "%s %lf", erefres[i], &edum);
376 snew(eaver, ngroups);
377 for (i = 0; (i < ngroups); i++)
379 for (k = 0; (k < nenergy); k++)
385 beta = 1.0/(BOLTZ*reftemp);
386 snew(efree, ngroups);
388 for (i = 0; (i < ngroups); i++)
391 for (k = 0; (k < nenergy); k++)
393 expE += exp(beta*(e[i][k]-eaver[i]));
395 efree[i] = log(expE/nenergy)/beta + eaver[i];
398 n = search_str2(neref, erefres, groups[i]);
401 edif[i] = efree[i]-eref[n];
406 fprintf(stderr, "WARNING: group %s not found "
407 "in reference energies.\n", groups[i]);
417 emid = 0.0; /*(emin+emax)*0.5;*/
418 egrp_nm[egTotal] = "total";
419 for (m = 0; (m < egNR+egSP); m++)
425 for (i = 0; (i < ngroups); i++)
427 for (j = i; (j < ngroups); j++)
429 if (emat[m][i][j] > emax)
431 emax = emat[m][i][j];
433 else if (emat[m][i][j] < emin)
435 emin = emat[m][i][j];
441 fprintf(stderr, "Matrix of %s energy is uniform at %f "
442 "(will not produce output).\n", egrp_nm[m], emax);
446 fprintf(stderr, "Matrix of %s energy ranges from %f to %f\n",
447 egrp_nm[m], emin, emax);
448 if ((bCutmax) || (emax > cutmax))
452 if ((bCutmin) || (emin < cutmin))
456 if ((emax == cutmax) || (emin == cutmin))
458 fprintf(stderr, "Energy range adjusted: %f to %f\n", emin, emax);
461 sprintf(fn, "%s%s", egrp_nm[m], ftp2fn(efXPM, NFILE, fnm));
462 sprintf(label, "%s Interaction Energies", egrp_nm[m]);
463 out = ffopen(fn, "w");
466 write_xpm(out, 0, label, "Energy (kJ/mol)",
467 "Residue Index", "Residue Index",
468 ngroups, ngroups, groupnr, groupnr, emat[m],
469 emid, emax, rmid, rhi, &nlevels);
471 else if (emax <= emid)
473 write_xpm(out, 0, label, "Energy (kJ/mol)",
474 "Residue Index", "Residue Index",
475 ngroups, ngroups, groupnr, groupnr, emat[m],
476 emin, emid, rlo, rmid, &nlevels);
480 write_xpm3(out, 0, label, "Energy (kJ/mol)",
481 "Residue Index", "Residue Index",
482 ngroups, ngroups, groupnr, groupnr, emat[m],
483 emin, emid, emax, rlo, rmid, rhi, &nlevels);
489 snew(etot, egNR+egSP);
490 for (m = 0; (m < egNR+egSP); m++)
492 snew(etot[m], ngroups);
493 for (i = 0; (i < ngroups); i++)
495 for (j = 0; (j < ngroups); j++)
497 etot[m][i] += emat[m][i][j];
502 out = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Mean Energy", "Residue", "kJ/mol",
504 xvgr_legend(out, 0, NULL, oenv);
506 for (m = 0; (m < egNR+egSP); m++)
510 fprintf(out, "@ legend string %d \"%s\"\n", j++, egrp_nm[m]);
515 fprintf(out, "@ legend string %d \"%s\"\n", j++, "Free");
519 fprintf(out, "@ legend string %d \"%s\"\n", j++, "Diff");
521 fprintf(out, "@TYPE xy\n");
522 fprintf(out, "#%3s", "grp");
523 for (m = 0; (m < egNR+egSP); m++)
527 fprintf(out, " %9s", egrp_nm[m]);
532 fprintf(out, " %9s", "Free");
536 fprintf(out, " %9s", "Diff");
539 for (i = 0; (i < ngroups); i++)
541 fprintf(out, "%3.0f", groupnr[i]);
542 for (m = 0; (m < egNR+egSP); m++)
546 fprintf(out, " %9.5g", etot[m][i]);
551 fprintf(out, " %9.5g", efree[i]);
555 fprintf(out, " %9.5g", edif[i]);
563 fprintf(stderr, "While typing at your keyboard, suddenly...\n"
564 "...nothing happens.\nWARNING: Not Implemented Yet\n");
566 out=ftp2FILE(efMAT,NFILE,fnm,"w");
569 for (k=0; (k<nenergy); k++) {
570 for (i=0; (i<ngroups); i++)
571 for (j=i+1; (j<ngroups); j++)
572 emat[i][j]=eneset[n][k];
573 sprintf(label,"t=%.0f ps",time[k]);
574 write_matrix(out,ngroups,1,ngroups,groupnr,emat,label,emin,emax,nlevels);