Enforced rotation: fixed torque calculation for FLEX potential when using mass-weighting
[gromacs/adressmacs.git] / src / tools / gmx_energy.c
blobcd299645b164f26c58635b1cae90ebae8cfa1193
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
3 *
4 * This source code is part of
5 *
6 * G R O M A C S
7 *
8 * GROningen MAchine for Chemical Simulations
9 *
10 * VERSION 3.2.0
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
33 * And Hey:
34 * Green Red Orange Magenta Azure Cyan Skyblue
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
40 #include <string.h>
41 #include <math.h>
42 #include <ctype.h>
44 #include "typedefs.h"
45 #include "gmx_fatal.h"
46 #include "vec.h"
47 #include "string2.h"
48 #include "smalloc.h"
49 #include "enxio.h"
50 #include "statutil.h"
51 #include "names.h"
52 #include "copyrite.h"
53 #include "macros.h"
54 #include "xvgr.h"
55 #include "gstat.h"
56 #include "physics.h"
57 #include "tpxio.h"
58 #include "viewit.h"
59 #include "mtop_util.h"
60 #include "gmx_ana.h"
63 static real minthird=-1.0/3.0,minsixth=-1.0/6.0;
65 typedef struct {
66 real sum;
67 real sum2;
68 } exactsum_t;
70 typedef struct {
71 real *ener;
72 exactsum_t *es;
73 gmx_bool bExactStat;
74 double av;
75 double rmsd;
76 double ee;
77 double slope;
78 } enerdat_t;
80 typedef struct {
81 gmx_large_int_t nsteps;
82 gmx_large_int_t npoints;
83 int nframes;
84 int *step;
85 int *steps;
86 int *points;
87 enerdat_t *s;
88 } enerdata_t;
90 static double mypow(double x,double y)
92 if (x > 0)
93 return pow(x,y);
94 else
95 return 0.0;
98 static int *select_it(int nre,char *nm[],int *nset)
100 gmx_bool *bE;
101 int n,k,j,i;
102 int *set;
103 gmx_bool bVerbose = TRUE;
105 if ((getenv("VERBOSE")) != NULL)
106 bVerbose = FALSE;
108 fprintf(stderr,"Select the terms you want from the following list\n");
109 fprintf(stderr,"End your selection with 0\n");
111 if ( bVerbose ) {
112 for(k=0; (k<nre); ) {
113 for(j=0; (j<4) && (k<nre); j++,k++)
114 fprintf(stderr," %3d=%14s",k+1,nm[k]);
115 fprintf(stderr,"\n");
119 snew(bE,nre);
120 do {
121 if(1 != scanf("%d",&n))
123 gmx_fatal(FARGS,"Error reading user input");
125 if ((n>0) && (n<=nre))
126 bE[n-1]=TRUE;
127 } while (n != 0);
129 snew(set,nre);
130 for(i=(*nset)=0; (i<nre); i++)
131 if (bE[i])
132 set[(*nset)++]=i;
134 sfree(bE);
136 return set;
139 static int strcount(const char *s1,const char *s2)
141 int n=0;
142 while (s1 && s2 && (toupper(s1[n]) == toupper(s2[n])))
143 n++;
144 return n;
147 static void chomp(char *buf)
149 int len = strlen(buf);
151 while ((len > 0) && (buf[len-1] == '\n')) {
152 buf[len-1] = '\0';
153 len--;
157 static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
159 gmx_bool *bE;
160 int n,k,kk,j,i,nmatch,nind,nss;
161 int *set;
162 gmx_bool bEOF,bVerbose = TRUE,bLong=FALSE;
163 char *ptr,buf[STRLEN];
164 const char *fm4="%3d %-14s";
165 const char *fm2="%3d %-34s";
166 char **newnm=NULL;
168 if ((getenv("VERBOSE")) != NULL)
169 bVerbose = FALSE;
171 fprintf(stderr,"\n");
172 fprintf(stderr,"Select the terms you want from the following list by\n");
173 fprintf(stderr,"selecting either (part of) the name or the number or a combination.\n");
174 fprintf(stderr,"End your selection with an empty line or a zero.\n");
175 fprintf(stderr,"-------------------------------------------------------------------\n");
177 snew(newnm,nre);
178 j = 0;
179 for(k=0; k<nre; k++) {
180 newnm[k] = strdup(nm[k].name);
181 /* Insert dashes in all the names */
182 while ((ptr = strchr(newnm[k],' ')) != NULL) {
183 *ptr = '-';
185 if ( bVerbose ) {
186 if (j == 0) {
187 if (k > 0) {
188 fprintf(stderr,"\n");
190 bLong = FALSE;
191 for(kk=k; kk<k+4; kk++) {
192 if (kk < nre && strlen(nm[kk].name) > 14) {
193 bLong = TRUE;
196 } else {
197 fprintf(stderr," ");
199 if (!bLong) {
200 fprintf(stderr,fm4,k+1,newnm[k]);
201 j++;
202 if (j == 4) {
203 j = 0;
205 } else {
206 fprintf(stderr,fm2,k+1,newnm[k]);
207 j++;
208 if (j == 2) {
209 j = 0;
214 if ( bVerbose ) {
215 fprintf(stderr,"\n\n");
218 snew(bE,nre);
220 bEOF = FALSE;
221 while (!bEOF && (fgets2(buf,STRLEN-1,stdin))) {
222 /* Remove newlines */
223 chomp(buf);
225 /* Remove spaces */
226 trim(buf);
228 /* Empty line means end of input */
229 bEOF = (strlen(buf) == 0);
230 if (!bEOF) {
231 ptr = buf;
232 do {
233 if (!bEOF) {
234 /* First try to read an integer */
235 nss = sscanf(ptr,"%d",&nind);
236 if (nss == 1) {
237 /* Zero means end of input */
238 if (nind == 0) {
239 bEOF = TRUE;
240 } else if ((1<=nind) && (nind<=nre)) {
241 bE[nind-1] = TRUE;
242 } else {
243 fprintf(stderr,"number %d is out of range\n",nind);
246 else {
247 /* Now try to read a string */
248 i = strlen(ptr);
249 nmatch = 0;
250 for(nind=0; nind<nre; nind++) {
251 if (gmx_strcasecmp(newnm[nind],ptr) == 0) {
252 bE[nind] = TRUE;
253 nmatch++;
256 if (nmatch == 0) {
257 i = strlen(ptr);
258 nmatch = 0;
259 for(nind=0; nind<nre; nind++) {
260 if (gmx_strncasecmp(newnm[nind],ptr,i) == 0) {
261 bE[nind] = TRUE;
262 nmatch++;
265 if (nmatch == 0) {
266 fprintf(stderr,"String '%s' does not match anything\n",ptr);
271 /* Look for the first space, and remove spaces from there */
272 if ((ptr = strchr(ptr,' ')) != NULL) {
273 trim(ptr);
275 } while (!bEOF && (ptr && (strlen(ptr) > 0)));
279 snew(set,nre);
280 for(i=(*nset)=0; (i<nre); i++)
281 if (bE[i])
282 set[(*nset)++]=i;
284 sfree(bE);
286 if (*nset == 0)
287 gmx_fatal(FARGS,"No energy terms selected");
289 for(i=0; (i<nre); i++)
290 sfree(newnm[i]);
291 sfree(newnm);
293 return set;
296 static void get_orires_parms(const char *topnm,
297 int *nor,int *nex,int **label,real **obs)
299 gmx_mtop_t mtop;
300 gmx_localtop_t *top;
301 t_inputrec ir;
302 t_iparams *ip;
303 int natoms,i;
304 t_iatom *iatom;
305 int nb;
306 matrix box;
308 read_tpx(topnm,&ir,box,&natoms,NULL,NULL,NULL,&mtop);
309 top = gmx_mtop_generate_local_top(&mtop,&ir);
311 ip = top->idef.iparams;
312 iatom = top->idef.il[F_ORIRES].iatoms;
314 /* Count how many distance restraint there are... */
315 nb = top->idef.il[F_ORIRES].nr;
316 if (nb == 0)
317 gmx_fatal(FARGS,"No orientation restraints in topology!\n");
319 *nor = nb/3;
320 *nex = 0;
321 snew(*label,*nor);
322 snew(*obs,*nor);
323 for(i=0; i<nb; i+=3) {
324 (*label)[i/3] = ip[iatom[i]].orires.label;
325 (*obs)[i/3] = ip[iatom[i]].orires.obs;
326 if (ip[iatom[i]].orires.ex >= *nex)
327 *nex = ip[iatom[i]].orires.ex+1;
329 fprintf(stderr,"Found %d orientation restraints with %d experiments",
330 *nor,*nex);
333 static int get_bounds(const char *topnm,
334 real **bounds,int **index,int **dr_pair,int *npairs,
335 gmx_mtop_t *mtop,gmx_localtop_t **ltop,t_inputrec *ir)
337 gmx_localtop_t *top;
338 t_functype *functype;
339 t_iparams *ip;
340 int natoms,i,j,k,type,ftype,natom;
341 t_ilist *disres;
342 t_iatom *iatom;
343 real *b;
344 int *ind,*pair;
345 int nb,label1;
346 matrix box;
348 read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,mtop);
349 snew(*ltop,1);
350 top = gmx_mtop_generate_local_top(mtop,ir);
351 *ltop = top;
353 functype = top->idef.functype;
354 ip = top->idef.iparams;
356 /* Count how many distance restraint there are... */
357 nb=top->idef.il[F_DISRES].nr;
358 if (nb == 0)
359 gmx_fatal(FARGS,"No distance restraints in topology!\n");
361 /* Allocate memory */
362 snew(b,nb);
363 snew(ind,nb);
364 snew(pair,nb+1);
366 /* Fill the bound array */
367 nb=0;
368 for(i=0; (i<top->idef.ntypes); i++) {
369 ftype = functype[i];
370 if (ftype == F_DISRES) {
372 label1 = ip[i].disres.label;
373 b[nb] = ip[i].disres.up1;
374 ind[nb] = label1;
375 nb++;
378 *bounds = b;
380 /* Fill the index array */
381 label1 = -1;
382 disres = &(top->idef.il[F_DISRES]);
383 iatom = disres->iatoms;
384 for(i=j=k=0; (i<disres->nr); ) {
385 type = iatom[i];
386 ftype = top->idef.functype[type];
387 natom = interaction_function[ftype].nratoms+1;
388 if (label1 != top->idef.iparams[type].disres.label) {
389 pair[j] = k;
390 label1 = top->idef.iparams[type].disres.label;
391 j ++;
393 k++;
394 i += natom;
396 pair[j] = k;
397 *npairs = k;
398 if (j != nb)
399 gmx_incons("get_bounds for distance restraints");
401 *index = ind;
402 *dr_pair = pair;
404 return nb;
407 static void calc_violations(real rt[],real rav3[],int nb,int index[],
408 real bounds[],real *viol,double *st,double *sa)
410 const real sixth=1.0/6.0;
411 int i,j;
412 double rsum,rav,sumaver,sumt;
414 sumaver = 0;
415 sumt = 0;
416 for(i=0; (i<nb); i++) {
417 rsum = 0.0;
418 rav = 0.0;
419 for(j=index[i]; (j<index[i+1]); j++) {
420 if (viol)
421 viol[j] += mypow(rt[j],-3.0);
422 rav += sqr(rav3[j]);
423 rsum += mypow(rt[j],-6);
425 rsum = max(0.0,mypow(rsum,-sixth)-bounds[i]);
426 rav = max(0.0,mypow(rav, -sixth)-bounds[i]);
428 sumt += rsum;
429 sumaver += rav;
431 *st = sumt;
432 *sa = sumaver;
435 static void analyse_disre(const char *voutfn, int nframes,
436 real violaver[], real bounds[], int index[],
437 int pair[], int nbounds,
438 const output_env_t oenv)
440 FILE *vout;
441 double sum,sumt,sumaver;
442 int i,j;
444 /* Subtract bounds from distances, to calculate violations */
445 calc_violations(violaver,violaver,
446 nbounds,pair,bounds,NULL,&sumt,&sumaver);
448 #ifdef DEBUG
449 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
450 sumaver);
451 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",
452 sumt);
453 #endif
454 vout=xvgropen(voutfn,"r\\S-3\\N average violations","DR Index","nm",
455 oenv);
456 sum = 0.0;
457 sumt = 0.0;
458 for(i=0; (i<nbounds); i++) {
459 /* Do ensemble averaging */
460 sumaver = 0;
461 for(j=pair[i]; (j<pair[i+1]); j++)
462 sumaver += sqr(violaver[j]/nframes);
463 sumaver = max(0.0,mypow(sumaver,minsixth)-bounds[i]);
465 sumt += sumaver;
466 sum = max(sum,sumaver);
467 fprintf(vout,"%10d %10.5e\n",index[i],sumaver);
469 #ifdef DEBUG
470 for(j=0; (j<dr.ndr); j++)
471 fprintf(vout,"%10d %10.5e\n",j,mypow(violaver[j]/nframes,minthird));
472 #endif
473 ffclose(vout);
475 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
476 sumt);
477 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",sum);
479 do_view(oenv,voutfn,"-graphtype bar");
482 static void einstein_visco(const char *fn,const char *fni,int nsets,
483 int nframes,real **sum,
484 real V,real T,int nsteps,double time[],
485 const output_env_t oenv)
487 FILE *fp0,*fp1;
488 double av[4],avold[4];
489 double fac,dt,di;
490 int i,j,m,nf4;
492 if (nframes < 1)
493 return;
495 dt = (time[1]-time[0]);
496 nf4 = nframes/4+1;
498 for(i=0; i<=nsets; i++)
499 avold[i] = 0;
500 fp0=xvgropen(fni,"Shear viscosity integral",
501 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N ps)",oenv);
502 fp1=xvgropen(fn,"Shear viscosity using Einstein relation",
503 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N)",oenv);
504 for(i=1; i<nf4; i++) {
505 fac = dt*nframes/nsteps;
506 for(m=0; m<=nsets; m++)
507 av[m] = 0;
508 for(j=0; j<nframes-i; j++) {
509 for(m=0; m<nsets; m++) {
510 di = sqr(fac*(sum[m][j+i]-sum[m][j]));
512 av[m] += di;
513 av[nsets] += di/nsets;
516 /* Convert to SI for the viscosity */
517 fac = (V*NANO*NANO*NANO*PICO*1e10)/(2*BOLTZMANN*T)/(nframes-i);
518 fprintf(fp0,"%10g",time[i]-time[0]);
519 for(m=0; (m<=nsets); m++) {
520 av[m] = fac*av[m];
521 fprintf(fp0," %10g",av[m]);
523 fprintf(fp0,"\n");
524 fprintf(fp1,"%10g",0.5*(time[i]+time[i-1])-time[0]);
525 for(m=0; (m<=nsets); m++) {
526 fprintf(fp1," %10g",(av[m]-avold[m])/dt);
527 avold[m] = av[m];
529 fprintf(fp1,"\n");
531 ffclose(fp0);
532 ffclose(fp1);
535 typedef struct {
536 gmx_large_int_t np;
537 double sum;
538 double sav;
539 double sav2;
540 } ee_sum_t;
542 typedef struct {
543 int b;
544 ee_sum_t sum;
545 gmx_large_int_t nst;
546 gmx_large_int_t nst_min;
547 } ener_ee_t;
549 static void clear_ee_sum(ee_sum_t *ees)
551 ees->sav = 0;
552 ees->sav2 = 0;
553 ees->np = 0;
554 ees->sum = 0;
557 static void add_ee_sum(ee_sum_t *ees,double sum,int np)
559 ees->np += np;
560 ees->sum += sum;
563 static void add_ee_av(ee_sum_t *ees)
565 double av;
567 av = ees->sum/ees->np;
568 ees->sav += av;
569 ees->sav2 += av*av;
570 ees->np = 0;
571 ees->sum = 0;
574 static double calc_ee2(int nb,ee_sum_t *ees)
576 return (ees->sav2/nb - dsqr(ees->sav/nb))/(nb - 1);
579 static void set_ee_av(ener_ee_t *eee)
581 if (debug)
583 char buf[STEPSTRSIZE];
584 fprintf(debug,"Storing average for err.est.: %s steps\n",
585 gmx_step_str(eee->nst,buf));
587 add_ee_av(&eee->sum);
588 eee->b++;
589 if (eee->b == 1 || eee->nst < eee->nst_min)
591 eee->nst_min = eee->nst;
593 eee->nst = 0;
596 static void calc_averages(int nset,enerdata_t *edat,int nbmin,int nbmax)
598 int nb,i,f,nee;
599 double sum,sum2,sump,see2;
600 gmx_large_int_t steps,np,p,bound_nb;
601 enerdat_t *ed;
602 exactsum_t *es;
603 gmx_bool bAllZero;
604 double x,sx,sy,sxx,sxy;
605 ener_ee_t *eee;
607 /* Check if we have exact statistics over all points */
608 for(i=0; i<nset; i++)
610 ed = &edat->s[i];
611 ed->bExactStat = FALSE;
612 if (edat->npoints > 0)
614 /* All energy file sum entries 0 signals no exact sums.
615 * But if all energy values are 0, we still have exact sums.
617 bAllZero = TRUE;
618 for(f=0; f<edat->nframes && !ed->bExactStat; f++)
620 if (ed->ener[i] != 0)
622 bAllZero = FALSE;
624 ed->bExactStat = (ed->es[f].sum != 0);
626 if (bAllZero)
628 ed->bExactStat = TRUE;
633 snew(eee,nbmax+1);
634 for(i=0; i<nset; i++)
636 ed = &edat->s[i];
638 sum = 0;
639 sum2 = 0;
640 np = 0;
641 sx = 0;
642 sy = 0;
643 sxx = 0;
644 sxy = 0;
645 for(nb=nbmin; nb<=nbmax; nb++)
647 eee[nb].b = 0;
648 clear_ee_sum(&eee[nb].sum);
649 eee[nb].nst = 0;
650 eee[nb].nst_min = 0;
652 for(f=0; f<edat->nframes; f++)
654 es = &ed->es[f];
656 if (ed->bExactStat)
658 /* Add the sum and the sum of variances to the totals. */
659 p = edat->points[f];
660 sump = es->sum;
661 sum2 += es->sum2;
662 if (np > 0)
664 sum2 += dsqr(sum/np - (sum + es->sum)/(np + p))
665 *np*(np + p)/p;
668 else
670 /* Add a single value to the sum and sum of squares. */
671 p = 1;
672 sump = ed->ener[f];
673 sum2 += dsqr(sump);
676 /* sum has to be increased after sum2 */
677 np += p;
678 sum += sump;
680 /* For the linear regression use variance 1/p.
681 * Note that sump is the sum, not the average, so we don't need p*.
683 x = edat->step[f] - 0.5*(edat->steps[f] - 1);
684 sx += p*x;
685 sy += sump;
686 sxx += p*x*x;
687 sxy += x*sump;
689 for(nb=nbmin; nb<=nbmax; nb++)
691 /* Check if the current end step is closer to the desired
692 * block boundary than the next end step.
694 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
695 if (eee[nb].nst > 0 &&
696 bound_nb - edat->step[f-1]*nb < edat->step[f]*nb - bound_nb)
698 set_ee_av(&eee[nb]);
700 if (f == 0)
702 eee[nb].nst = 1;
704 else
706 eee[nb].nst += edat->step[f] - edat->step[f-1];
708 if (ed->bExactStat)
710 add_ee_sum(&eee[nb].sum,es->sum,edat->points[f]);
712 else
714 add_ee_sum(&eee[nb].sum,edat->s[i].ener[f],1);
716 bound_nb = (edat->step[0]-1)*nb + edat->nsteps*(eee[nb].b+1);
717 if (edat->step[f]*nb >= bound_nb)
719 set_ee_av(&eee[nb]);
724 edat->s[i].av = sum/np;
725 if (ed->bExactStat)
727 edat->s[i].rmsd = sqrt(sum2/np);
729 else
731 edat->s[i].rmsd = sqrt(sum2/np - dsqr(edat->s[i].av));
734 if (edat->nframes > 1)
736 edat->s[i].slope = (np*sxy - sx*sy)/(np*sxx - sx*sx);
738 else
740 edat->s[i].slope = 0;
743 nee = 0;
744 see2 = 0;
745 for(nb=nbmin; nb<=nbmax; nb++)
747 /* Check if we actually got nb blocks and if the smallest
748 * block is not shorter than 80% of the average.
750 if (debug)
752 char buf1[STEPSTRSIZE],buf2[STEPSTRSIZE];
753 fprintf(debug,"Requested %d blocks, we have %d blocks, min %s nsteps %s\n",
754 nb,eee[nb].b,
755 gmx_step_str(eee[nb].nst_min,buf1),
756 gmx_step_str(edat->nsteps,buf2));
758 if (eee[nb].b == nb && 5*nb*eee[nb].nst_min >= 4*edat->nsteps)
760 see2 += calc_ee2(nb,&eee[nb].sum);
761 nee++;
764 if (nee > 0)
766 edat->s[i].ee = sqrt(see2/nee);
768 else
770 edat->s[i].ee = -1;
773 sfree(eee);
776 static enerdata_t *calc_sum(int nset,enerdata_t *edat,int nbmin,int nbmax)
778 enerdata_t *esum;
779 enerdat_t *s;
780 int f,i;
781 double sum;
783 snew(esum,1);
784 *esum = *edat;
785 snew(esum->s,1);
786 s = &esum->s[0];
787 snew(s->ener,esum->nframes);
788 snew(s->es ,esum->nframes);
790 s->bExactStat = TRUE;
791 s->slope = 0;
792 for(i=0; i<nset; i++)
794 if (!edat->s[i].bExactStat)
796 s->bExactStat = FALSE;
798 s->slope += edat->s[i].slope;
801 for(f=0; f<edat->nframes; f++)
803 sum = 0;
804 for(i=0; i<nset; i++)
806 sum += edat->s[i].ener[f];
808 s->ener[f] = sum;
809 sum = 0;
810 for(i=0; i<nset; i++)
812 sum += edat->s[i].es[f].sum;
814 s->es[f].sum = sum;
815 s->es[f].sum2 = 0;
818 calc_averages(1,esum,nbmin,nbmax);
820 return esum;
823 static char *ee_pr(double ee,char *buf)
825 char tmp[100];
826 double rnd;
828 if (ee < 0)
830 sprintf(buf,"%s","--");
832 else
834 /* Round to two decimals by printing. */
835 sprintf(tmp,"%.1e",ee);
836 sscanf(tmp,"%lf",&rnd);
837 sprintf(buf,"%g",rnd);
840 return buf;
843 static void analyse_ener(gmx_bool bCorr,const char *corrfn,
844 gmx_bool bFee,gmx_bool bSum,gmx_bool bFluct,gmx_bool bTempFluct,
845 gmx_bool bVisco,const char *visfn,int nmol,
846 int nconstr,
847 gmx_large_int_t start_step,double start_t,
848 gmx_large_int_t step,double t,
849 double time[], real reftemp,
850 enerdata_t *edat,
851 int nset,int set[],gmx_bool *bIsEner,
852 char **leg,gmx_enxnm_t *enm,
853 real Vaver,real ezero,
854 int nbmin,int nbmax,
855 const output_env_t oenv)
857 FILE *fp;
858 /* Check out the printed manual for equations! */
859 double Dt,aver,stddev,errest,delta_t,totaldrift;
860 enerdata_t *esum=NULL;
861 real xxx,integral,intBulk;
862 real sfrac,oldfrac,diffsum,diffav,fstep,pr_aver,pr_stddev,pr_errest;
863 double beta=0,expE,expEtot,*fee=NULL;
864 gmx_large_int_t nsteps;
865 int nexact,nnotexact;
866 double x1m,x1mk;
867 real Temp=-1,Pres=-1,VarV=-1,VarT=-1,VarEtot=-1,AvEtot=0,VarEnthalpy=-1;
868 int i,j,nout;
869 real chi2;
870 char buf[256],eebuf[100];
872 nsteps = step - start_step + 1;
873 if (nsteps < 1) {
874 fprintf(stdout,"Not enough steps (%s) for statistics\n",
875 gmx_step_str(nsteps,buf));
877 else {
878 /* Calculate the time difference */
879 delta_t = t - start_t;
881 fprintf(stdout,"\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
882 gmx_step_str(nsteps,buf),start_t,t,nset);
884 calc_averages(nset,edat,nbmin,nbmax);
886 if (bSum) {
887 esum = calc_sum(nset,edat,nbmin,nbmax);
890 if (edat->npoints == 0) {
891 nexact = 0;
892 nnotexact = nset;
893 } else {
894 nexact = 0;
895 nnotexact = 0;
896 for(i=0; (i<nset); i++) {
897 if (edat->s[i].bExactStat) {
898 nexact++;
899 } else {
900 nnotexact++;
905 if (nnotexact == 0) {
906 fprintf(stdout,"All statistics are over %s points\n",
907 gmx_step_str(edat->npoints,buf));
908 } else if (nexact == 0 || edat->npoints == edat->nframes) {
909 fprintf(stdout,"All statistics are over %d points (frames)\n",
910 edat->nframes);
911 } else {
912 fprintf(stdout,"The term%s",nnotexact==1 ? "" : "s");
913 for(i=0; (i<nset); i++) {
914 if (!edat->s[i].bExactStat) {
915 fprintf(stdout," '%s'",leg[i]);
918 fprintf(stdout," %s has statistics over %d points (frames)\n",
919 nnotexact==1 ? "is" : "are",edat->nframes);
920 fprintf(stdout,"All other statistics are over %s points\n",
921 gmx_step_str(edat->npoints,buf));
923 fprintf(stdout,"\n");
925 fprintf(stdout,"%-24s %10s %10s %10s %10s",
926 "Energy","Average","Err.Est.","RMSD","Tot-Drift");
927 if (bFee)
928 fprintf(stdout," %10s\n","-kT ln<e^(E/kT)>");
929 else
930 fprintf(stdout,"\n");
931 fprintf(stdout,"-------------------------------------------------------------------------------\n");
933 /* Initiate locals, only used with -sum */
934 expEtot=0;
935 if (bFee) {
936 beta = 1.0/(BOLTZ*reftemp);
937 snew(fee,nset);
939 for(i=0; (i<nset); i++) {
940 aver = edat->s[i].av;
941 stddev = edat->s[i].rmsd;
942 errest = edat->s[i].ee;
944 if (bFee) {
945 expE = 0;
946 for(j=0; (j<edat->nframes); j++) {
947 expE += exp(beta*(edat->s[i].ener[j] - aver)/nmol);
949 if (bSum)
950 expEtot+=expE/edat->nframes;
952 fee[i] = log(expE/edat->nframes)/beta + aver/nmol;
954 if (strstr(leg[i],"empera") != NULL) {
955 VarT = sqr(stddev);
956 Temp = aver;
957 } else if (strstr(leg[i],"olum") != NULL) {
958 VarV = sqr(stddev);
959 Vaver= aver;
960 } else if (strstr(leg[i],"essure") != NULL) {
961 Pres = aver;
962 } else if (strstr(leg[i],"otal") != NULL) {
963 VarEtot = sqr(stddev);
964 AvEtot = aver;
965 } else if (strstr(leg[i],"nthalpy") != NULL) {
966 VarEnthalpy = sqr(stddev);
968 if (bIsEner[i]) {
969 pr_aver = aver/nmol-ezero;
970 pr_stddev = stddev/nmol;
971 pr_errest = errest/nmol;
973 else {
974 pr_aver = aver;
975 pr_stddev = stddev;
976 pr_errest = errest;
979 /* Multiply the slope in steps with the number of steps taken */
980 totaldrift = (edat->nsteps - 1)*edat->s[i].slope;
981 if (bIsEner[i])
983 totaldrift /= nmol;
986 fprintf(stdout,"%-24s %10g %10s %10g %10g",
987 leg[i],pr_aver,ee_pr(pr_errest,eebuf),pr_stddev,totaldrift);
988 if (bFee)
989 fprintf(stdout," %10g",fee[i]);
991 fprintf(stdout," (%s)\n",enm[set[i]].unit);
993 if (bFluct) {
994 for(j=0; (j<edat->nframes); j++)
995 edat->s[i].ener[j] -= aver;
998 if (bSum) {
999 totaldrift = (edat->nsteps - 1)*esum->s[0].slope;
1000 fprintf(stdout,"%-24s %10g %10s %10s %10g (%s)",
1001 "Total",esum->s[0].av/nmol,ee_pr(esum->s[0].ee/nmol,eebuf),
1002 "--",totaldrift/nmol,enm[set[0]].unit);
1003 /* pr_aver,pr_stddev,a,totaldrift */
1004 if (bFee)
1005 fprintf(stdout," %10g %10g\n",
1006 log(expEtot)/beta + esum->s[0].av/nmol,log(expEtot)/beta);
1007 else
1008 fprintf(stdout,"\n");
1010 if (bTempFluct && Temp != -1) {
1011 printf("\nTemperature dependent fluctuation properties at T = %g. #constr/mol = %d\n",Temp,nconstr);
1012 if (nmol < 2)
1013 printf("Warning: nmol = %d, this may not be what you want.\n",
1014 nmol);
1015 if (VarV != -1) {
1016 real tmp = VarV/(Vaver*BOLTZ*Temp*PRESFAC);
1018 printf("Isothermal Compressibility: %10g /%s\n",
1019 tmp,unit_pres_bar);
1020 printf("Adiabatic bulk modulus: %10g %s\n",
1021 1.0/tmp,unit_pres_bar);
1023 if (VarEnthalpy != -1) {
1024 real Cp = 1000*((VarEnthalpy/nmol)/(BOLTZ*Temp*Temp) -
1025 0.5*BOLTZ*nconstr);
1026 printf("Heat capacity at constant pressure Cp: %10g J/mol K\n",Cp);
1028 if ((VarV != -1) && (VarEnthalpy != -1)) {
1029 real aP = (sqrt(VarEnthalpy*VarV/nmol))/(BOLTZ*Vaver*Temp*Temp);
1030 printf("Thermal expansion coefficient alphaP: %10g 1/K\n",aP);
1032 if ((VarV == -1) && (VarEtot != -1)) {
1033 real Cv = 1000*((VarEtot/nmol)/(BOLTZ*Temp*Temp) -
1034 0.5*BOLTZ*nconstr);
1035 printf("Heat capacity at constant volume Cv: %10g J/mol K\n",Cv);
1037 please_cite(stdout,"Allen1987a");
1039 /* Do correlation function */
1040 if (edat->nframes > 1)
1042 Dt = delta_t/(edat->nframes - 1);
1044 else
1046 Dt = 0;
1048 if (bVisco) {
1049 const char* leg[] = { "Shear", "Bulk" };
1050 real factor;
1051 real **eneset;
1052 real **enesum;
1054 /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
1056 /* Symmetrise tensor! (and store in first three elements)
1057 * And subtract average pressure!
1059 snew(eneset,12);
1060 for(i=0; i<12; i++) {
1061 snew(eneset[i],edat->nframes);
1063 snew(enesum,3);
1064 for(i=0; i<3; i++) {
1065 snew(enesum[i],edat->nframes);
1067 for(i=0; (i<edat->nframes); i++) {
1068 eneset[0][i] = 0.5*(edat->s[1].ener[i]+edat->s[3].ener[i]);
1069 eneset[1][i] = 0.5*(edat->s[2].ener[i]+edat->s[6].ener[i]);
1070 eneset[2][i] = 0.5*(edat->s[5].ener[i]+edat->s[7].ener[i]);
1071 for(j=3; j<=11; j++) {
1072 eneset[j][i] = edat->s[j].ener[i];
1074 eneset[11][i] -= Pres;
1075 enesum[0][i] = 0.5*(edat->s[1].es[i].sum+edat->s[3].es[i].sum);
1076 enesum[1][i] = 0.5*(edat->s[2].es[i].sum+edat->s[6].es[i].sum);
1077 enesum[2][i] = 0.5*(edat->s[5].es[i].sum+edat->s[7].es[i].sum);
1080 einstein_visco("evisco.xvg","eviscoi.xvg",
1081 3,edat->nframes,enesum,Vaver,Temp,nsteps,time,oenv);
1083 /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
1084 /* Do it for shear viscosity */
1085 strcpy(buf,"Shear Viscosity");
1086 low_do_autocorr(corrfn,oenv,buf,edat->nframes,3,
1087 (edat->nframes+1)/2,eneset,Dt,
1088 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1090 /* Now for bulk viscosity */
1091 strcpy(buf,"Bulk Viscosity");
1092 low_do_autocorr(corrfn,oenv,buf,edat->nframes,1,
1093 (edat->nframes+1)/2,&(eneset[11]),Dt,
1094 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
1096 factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
1097 fp=xvgropen(visfn,buf,"Time (ps)","\\8h\\4 (cp)",oenv);
1098 xvgr_legend(fp,asize(leg),leg,oenv);
1100 /* Use trapezium rule for integration */
1101 integral = 0;
1102 intBulk = 0;
1103 nout = get_acfnout();
1104 if ((nout < 2) || (nout >= edat->nframes/2))
1105 nout = edat->nframes/2;
1106 for(i=1; (i<nout); i++)
1108 integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
1109 intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
1110 fprintf(fp,"%10g %10g %10g\n",(i*Dt),integral,intBulk);
1112 ffclose(fp);
1114 else if (bCorr) {
1115 if (bFluct)
1116 strcpy(buf,"Autocorrelation of Energy Fluctuations");
1117 else
1118 strcpy(buf,"Energy Autocorrelation");
1119 #if 0
1120 do_autocorr(corrfn,oenv,buf,edat->nframes,
1121 bSum ? 1 : nset,
1122 bSum ? &edat->s[nset-1].ener : eneset,
1123 (delta_t/edat->nframes),eacNormal,FALSE);
1124 #endif
1129 static void print_time(FILE *fp,double t)
1131 fprintf(fp,"%12.6f",t);
1134 static void print1(FILE *fp,gmx_bool bDp,real e)
1136 if (bDp)
1137 fprintf(fp," %16.12f",e);
1138 else
1139 fprintf(fp," %10.6f",e);
1142 static void fec(const char *ene2fn, const char *runavgfn,
1143 real reftemp, int nset, int set[], char *leg[],
1144 enerdata_t *edat, double time[],
1145 const output_env_t oenv)
1147 const char* ravgleg[] = { "\\8D\\4E = E\\sB\\N-E\\sA\\N",
1148 "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N" };
1149 FILE *fp;
1150 ener_file_t enx;
1151 int nre,timecheck,step,nenergy,nenergy2,maxenergy;
1152 int i,j;
1153 gmx_bool bCont;
1154 real aver, beta;
1155 real **eneset2;
1156 double dE, sum;
1157 gmx_enxnm_t *enm=NULL;
1158 t_enxframe *fr;
1159 char buf[22];
1161 /* read second energy file */
1162 snew(fr,1);
1163 enm = NULL;
1164 enx = open_enx(ene2fn,"r");
1165 do_enxnms(enx,&(fr->nre),&enm);
1167 snew(eneset2,nset+1);
1168 nenergy2=0;
1169 maxenergy=0;
1170 timecheck=0;
1171 do {
1172 /* This loop searches for the first frame (when -b option is given),
1173 * or when this has been found it reads just one energy frame
1175 do {
1176 bCont = do_enx(enx,fr);
1178 if (bCont)
1179 timecheck = check_times(fr->t);
1181 } while (bCont && (timecheck < 0));
1183 /* Store energies for analysis afterwards... */
1184 if ((timecheck == 0) && bCont) {
1185 if (fr->nre > 0) {
1186 if ( nenergy2 >= maxenergy ) {
1187 maxenergy += 1000;
1188 for(i=0; i<=nset; i++)
1189 srenew(eneset2[i],maxenergy);
1191 if (fr->t != time[nenergy2])
1192 fprintf(stderr,"\nWARNING time mismatch %g!=%g at frame %s\n",
1193 fr->t, time[nenergy2], gmx_step_str(fr->step,buf));
1194 for(i=0; i<nset; i++)
1195 eneset2[i][nenergy2] = fr->ener[set[i]].e;
1196 nenergy2++;
1199 } while (bCont && (timecheck == 0));
1201 /* check */
1202 if (edat->nframes != nenergy2) {
1203 fprintf(stderr,"\nWARNING file length mismatch %d!=%d\n",
1204 edat->nframes,nenergy2);
1206 nenergy = min(edat->nframes,nenergy2);
1208 /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
1209 fp=NULL;
1210 if (runavgfn) {
1211 fp=xvgropen(runavgfn,"Running average free energy difference",
1212 "Time (" unit_time ")","\\8D\\4E (" unit_energy ")",oenv);
1213 xvgr_legend(fp,asize(ravgleg),ravgleg,oenv);
1215 fprintf(stdout,"\n%-24s %10s\n",
1216 "Energy","dF = -kT ln < exp(-(EB-EA)/kT) >A");
1217 sum=0;
1218 beta = 1.0/(BOLTZ*reftemp);
1219 for(i=0; i<nset; i++) {
1220 if (gmx_strcasecmp(leg[i],enm[set[i]].name)!=0)
1221 fprintf(stderr,"\nWARNING energy set name mismatch %s!=%s\n",
1222 leg[i],enm[set[i]].name);
1223 for(j=0; j<nenergy; j++) {
1224 dE = eneset2[i][j] - edat->s[i].ener[j];
1225 sum += exp(-dE*beta);
1226 if (fp)
1227 fprintf(fp,"%10g %10g %10g\n",
1228 time[j], dE, -BOLTZ*reftemp*log(sum/(j+1)) );
1230 aver = -BOLTZ*reftemp*log(sum/nenergy);
1231 fprintf(stdout,"%-24s %10g\n",leg[i],aver);
1233 if(fp) ffclose(fp);
1234 sfree(fr);
1238 static void do_dhdl(t_enxframe *fr, FILE **fp_dhdl, const char *filename,
1239 int *blocks, int *hists, int *samples, int *nlambdas,
1240 const output_env_t oenv)
1242 const char *dhdl="dH/d\\lambda",*deltag="\\DeltaH",*lambda="\\lambda";
1243 char title[STRLEN],label_x[STRLEN],label_y[STRLEN], legend[STRLEN];
1244 char buf[STRLEN];
1245 gmx_bool first=FALSE;
1246 int nblock_hist=0, nblock_dh=0, nblock_dhcoll=0;
1247 int i,j,k;
1248 /* coll data */
1249 double temp=0, start_time=0, delta_time=0, start_lambda=0, delta_lambda=0;
1250 static int setnr=0;
1252 /* now count the blocks & handle the global dh data */
1253 for(i=0;i<fr->nblock;i++)
1255 if (fr->block[i].id == enxDHHIST)
1257 nblock_hist++;
1259 else if (fr->block[i].id == enxDH)
1261 nblock_dh++;
1263 else if (fr->block[i].id == enxDHCOLL)
1265 nblock_dhcoll++;
1266 if ( (fr->block[i].nsub < 1) ||
1267 (fr->block[i].sub[0].type != xdr_datatype_double) ||
1268 (fr->block[i].sub[0].nr < 5))
1270 gmx_fatal(FARGS, "Unexpected block data");
1273 /* read the data from the DHCOLL block */
1274 temp = fr->block[i].sub[0].dval[0];
1275 start_time = fr->block[i].sub[0].dval[1];
1276 delta_time = fr->block[i].sub[0].dval[2];
1277 start_lambda = fr->block[i].sub[0].dval[3];
1278 delta_lambda = fr->block[i].sub[0].dval[4];
1282 if (nblock_hist == 0 && nblock_dh == 0)
1284 /* don't do anything */
1285 return;
1287 if (nblock_hist>0 && nblock_dh>0)
1289 gmx_fatal(FARGS, "This energy file contains both histogram dhdl data and non-histogram dhdl data. Don't know what to do.");
1291 if (! *fp_dhdl )
1293 if (nblock_dh>0)
1295 sprintf(title,"%s, %s",dhdl,deltag);
1296 sprintf(label_x,"%s (%s)","Time",unit_time);
1297 sprintf(label_y,"(%s)",unit_energy);
1299 else
1301 sprintf(title,"N(%s)",deltag);
1302 sprintf(label_x,"%s (%s)",deltag,unit_energy);
1303 sprintf(label_y,"Samples");
1305 *fp_dhdl=xvgropen_type(filename, title, label_x, label_y, exvggtXNY,
1306 oenv);
1307 sprintf(buf,"T = %g (K), %s = %g", temp, lambda, start_lambda);
1308 xvgr_subtitle(*fp_dhdl,buf,oenv);
1309 first=TRUE;
1314 (*hists)+=nblock_hist;
1315 (*blocks)+=nblock_dh;
1316 (*nlambdas) = nblock_hist+nblock_dh;
1319 /* write the data */
1320 if (nblock_hist > 0)
1322 gmx_large_int_t sum=0;
1323 /* histograms */
1324 for(i=0;i<fr->nblock;i++)
1326 t_enxblock *blk=&(fr->block[i]);
1327 if (blk->id==enxDHHIST)
1329 double foreign_lambda, dx;
1330 gmx_large_int_t x0;
1331 int nhist, derivative;
1333 /* check the block types etc. */
1334 if ( (blk->nsub < 2) ||
1335 (blk->sub[0].type != xdr_datatype_double) ||
1336 (blk->sub[1].type != xdr_datatype_large_int) ||
1337 (blk->sub[0].nr < 2) ||
1338 (blk->sub[1].nr < 2) )
1340 gmx_fatal(FARGS, "Unexpected block data in file");
1342 foreign_lambda=blk->sub[0].dval[0];
1343 dx=blk->sub[0].dval[1];
1344 nhist=blk->sub[1].lval[0];
1345 derivative=blk->sub[1].lval[1];
1346 for(j=0;j<nhist;j++)
1348 const char *lg[1];
1349 x0=blk->sub[1].lval[2+j];
1351 if (!derivative)
1353 sprintf(legend,
1354 "N(%s(%s=%g) | %s=%g)",
1355 deltag, lambda, foreign_lambda,
1356 lambda, start_lambda);
1358 else
1360 sprintf(legend, "N(%s | %s=%g)",
1361 dhdl, lambda, start_lambda);
1364 lg[0]=legend;
1365 xvgr_new_dataset(*fp_dhdl, setnr, 1, lg, oenv);
1366 setnr++;
1367 for(k=0;k<blk->sub[j+2].nr;k++)
1369 int hist;
1370 double xmin, xmax;
1372 hist=blk->sub[j+2].ival[k];
1373 xmin=(x0+k)*dx;
1374 xmax=(x0+k+1)*dx;
1375 fprintf(*fp_dhdl,"%g %d\n%g %d\n", xmin, hist,
1376 xmax, hist);
1377 sum+=hist;
1379 /* multiple histogram data blocks in one histogram
1380 mean that the second one is the reverse of the first one:
1381 for dhdl derivatives, it's important to know both the
1382 maximum and minimum values */
1383 dx=-dx;
1388 (*samples) += (int)(sum/nblock_hist);
1390 else
1392 /* raw dh */
1393 int len=0;
1394 char **setnames=NULL;
1395 int nnames=nblock_dh;
1397 if (fabs(delta_lambda) > 1e-9)
1399 nnames++;
1401 if (first)
1403 snew(setnames, nnames);
1405 j=0;
1407 if (fabs(delta_lambda) > 1e-9)
1409 /* lambda is a plotted value */
1410 setnames[j]=gmx_strdup(lambda);
1411 j++;
1415 for(i=0;i<fr->nblock;i++)
1417 t_enxblock *blk=&(fr->block[i]);
1418 if (blk->id == enxDH)
1420 if (first)
1422 /* do the legends */
1423 int derivative;
1424 double foreign_lambda;
1426 derivative=blk->sub[0].ival[0];
1427 foreign_lambda=blk->sub[1].dval[0];
1429 if (derivative)
1431 sprintf(buf, "%s %s %g",dhdl,lambda,start_lambda);
1433 else
1435 sprintf(buf, "%s %s %g",deltag,lambda,
1436 foreign_lambda);
1438 setnames[j] = gmx_strdup(buf);
1439 j++;
1442 if (len == 0)
1444 len=blk->sub[2].nr;
1446 else
1448 if (len!=blk->sub[2].nr)
1450 gmx_fatal(FARGS,
1451 "Length inconsistency in dhdl data");
1458 if (first)
1460 xvgr_legend(*fp_dhdl, nblock_dh, (const char**)setnames, oenv);
1461 setnr += nblock_dh;
1462 for(i=0;i<nblock_dh;i++)
1464 sfree(setnames[i]);
1466 sfree(setnames);
1469 (*samples) += len;
1470 for(i=0;i<len;i++)
1472 double time=start_time + delta_time*i;
1474 fprintf(*fp_dhdl,"%.4f", time);
1475 if (fabs(delta_lambda) > 1e-9)
1477 double lambda_now=i*delta_lambda + start_lambda;
1478 fprintf(*fp_dhdl," %.4f", lambda_now);
1480 for(j=0;j<fr->nblock;j++)
1482 t_enxblock *blk=&(fr->block[j]);
1483 if (blk->id == enxDH)
1485 double value;
1486 if (blk->sub[2].type == xdr_datatype_float)
1488 value=blk->sub[2].fval[i];
1490 else
1492 value=blk->sub[2].dval[i];
1494 fprintf(*fp_dhdl," %g", value);
1497 fprintf(*fp_dhdl, "\n");
1503 int gmx_energy(int argc,char *argv[])
1505 const char *desc[] = {
1507 "g_energy extracts energy components or distance restraint",
1508 "data from an energy file. The user is prompted to interactively",
1509 "select the energy terms she wants.[PAR]",
1511 "Average, RMSD and drift are calculated with full precision from the",
1512 "simulation (see printed manual). Drift is calculated by performing",
1513 "a LSQ fit of the data to a straight line. The reported total drift",
1514 "is the difference of the fit at the first and last point.",
1515 "An error estimate of the average is given based on a block averages",
1516 "over 5 blocks using the full precision averages. The error estimate",
1517 "can be performed over multiple block lengths with the options",
1518 "[TT]-nbmin[tt] and [TT]-nbmax[tt].",
1519 "Note that in most cases the energy files contains averages over all",
1520 "MD steps, or over many more points than the number of frames in",
1521 "energy file. This makes the g_energy statistics output more accurate",
1522 "than the xvg output. When exact averages are not present in the energy",
1523 "file the statistics mentioned above is simply over the single, per-frame",
1524 "energy values.[PAR]",
1526 "The term fluctuation gives the RMSD around the LSQ fit.[PAR]",
1528 "Some fluctuation-dependent properties can be calculated provided",
1529 "the correct energy terms are selected. The following properties",
1530 "will be computed:[BR]",
1531 "Property Energy terms needed[BR]",
1532 "---------------------------------------------------[BR]",
1533 "Heat capacity Cp (NPT sims): Enthalpy, Temp [BR]",
1534 "Heat capacity Cv (NVT sims): Etot, Temp [BR]",
1535 "Thermal expansion coeff. (NPT): Enthalpy, Vol, Temp[BR]",
1536 "Isothermal compressibility: Vol, Temp [BR]",
1537 "Adiabatic bulk modulus: Vol, Temp [BR]",
1538 "---------------------------------------------------[BR]",
1539 "You always need to set the number of molecules [TT]-nmol[tt], and,",
1540 "if you used constraints in your simulations you will need to give",
1541 "the number of constraints per molecule [TT]-nconstr[tt] in order to",
1542 "correct for this: (nconstr/2) kB is subtracted from the heat",
1543 "capacity in this case. For instance in the case of rigid water",
1544 "you need to give the value 3 to this option.[PAR]",
1546 "When the [TT]-viol[tt] option is set, the time averaged",
1547 "violations are plotted and the running time-averaged and",
1548 "instantaneous sum of violations are recalculated. Additionally",
1549 "running time-averaged and instantaneous distances between",
1550 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
1552 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
1553 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
1554 "The first two options plot the orientation, the last three the",
1555 "deviations of the orientations from the experimental values.",
1556 "The options that end on an 'a' plot the average over time",
1557 "as a function of restraint. The options that end on a 't'",
1558 "prompt the user for restraint label numbers and plot the data",
1559 "as a function of time. Option [TT]-odr[tt] plots the RMS",
1560 "deviation as a function of restraint.",
1561 "When the run used time or ensemble averaged orientation restraints,",
1562 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
1563 "not ensemble-averaged orientations and deviations instead of",
1564 "the time and ensemble averages.[PAR]",
1566 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
1567 "tensor for each orientation restraint experiment. With option",
1568 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
1570 "Option [TT]-odh[tt] extracts and plots the free energy data",
1571 "(Hamiltoian differences and/or the Hamiltonian derivative dhdl)",
1572 "from the ener.edr file.[PAR]",
1574 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
1575 "difference with an ideal gas state: [BR]",
1576 " Delta A = A(N,V,T) - A_idgas(N,V,T) = kT ln < e^(Upot/kT) >[BR]",
1577 " Delta G = G(N,p,T) - G_idgas(N,p,T) = kT ln < e^(Upot/kT) >[BR]",
1578 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
1579 "the average is over the ensemble (or time in a trajectory).",
1580 "Note that this is in principle",
1581 "only correct when averaging over the whole (Boltzmann) ensemble",
1582 "and using the potential energy. This also allows for an entropy",
1583 "estimate using:[BR]",
1584 " Delta S(N,V,T) = S(N,V,T) - S_idgas(N,V,T) = (<Upot> - Delta A)/T[BR]",
1585 " Delta S(N,p,T) = S(N,p,T) - S_idgas(N,p,T) = (<Upot> + pV - Delta G)/T",
1586 "[PAR]",
1588 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
1589 "difference is calculated dF = -kT ln < e ^ -(EB-EA)/kT >A ,",
1590 "where EA and EB are the energies from the first and second energy",
1591 "files, and the average is over the ensemble A. [BB]NOTE[bb] that",
1592 "the energies must both be calculated from the same trajectory."
1595 static gmx_bool bSum=FALSE,bFee=FALSE,bPrAll=FALSE,bFluct=FALSE;
1596 static gmx_bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE;
1597 static int skip=0,nmol=1,nconstr=0,nbmin=5,nbmax=5;
1598 static real reftemp=300.0,ezero=0;
1599 t_pargs pa[] = {
1600 { "-fee", FALSE, etBOOL, {&bFee},
1601 "Do a free energy estimate" },
1602 { "-fetemp", FALSE, etREAL,{&reftemp},
1603 "Reference temperature for free energy calculation" },
1604 { "-zero", FALSE, etREAL, {&ezero},
1605 "Subtract a zero-point energy" },
1606 { "-sum", FALSE, etBOOL, {&bSum},
1607 "Sum the energy terms selected rather than display them all" },
1608 { "-dp", FALSE, etBOOL, {&bDp},
1609 "Print energies in high precision" },
1610 { "-nbmin", FALSE, etINT, {&nbmin},
1611 "Minimum number of blocks for error estimate" },
1612 { "-nbmax", FALSE, etINT, {&nbmax},
1613 "Maximum number of blocks for error estimate" },
1614 { "-mutot",FALSE, etBOOL, {&bMutot},
1615 "Compute the total dipole moment from the components" },
1616 { "-skip", FALSE, etINT, {&skip},
1617 "Skip number of frames between data points" },
1618 { "-aver", FALSE, etBOOL, {&bPrAll},
1619 "Also print the exact average and rmsd stored in the energy frames (only when 1 term is requested)" },
1620 { "-nmol", FALSE, etINT, {&nmol},
1621 "Number of molecules in your sample: the energies are divided by this number" },
1622 { "-nconstr", FALSE, etINT, {&nconstr},
1623 "Number of constraints per molecule. Necessary for calculating the heat capacity" },
1624 { "-fluc", FALSE, etBOOL, {&bFluct},
1625 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
1626 { "-orinst", FALSE, etBOOL, {&bOrinst},
1627 "Analyse instantaneous orientation data" },
1628 { "-ovec", FALSE, etBOOL, {&bOvec},
1629 "Also plot the eigenvectors with -oten" }
1631 const char* drleg[] = {
1632 "Running average",
1633 "Instantaneous"
1635 static const char *setnm[] = {
1636 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
1637 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
1638 "Volume", "Pressure"
1641 FILE *out=NULL,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
1642 FILE *fp_dhdl=NULL;
1643 FILE **drout;
1644 ener_file_t fp;
1645 int timecheck=0;
1646 gmx_mtop_t mtop;
1647 gmx_localtop_t *top=NULL;
1648 t_inputrec ir;
1649 t_energy **ee;
1650 enerdata_t edat;
1651 gmx_enxnm_t *enm=NULL;
1652 t_enxframe *frame,*fr=NULL;
1653 int cur=0;
1654 #define NEXT (1-cur)
1655 int nre,teller,teller_disre,nfr;
1656 gmx_large_int_t start_step;
1657 int nor=0,nex=0,norfr=0,enx_i=0;
1658 real start_t;
1659 real *bounds=NULL,*violaver=NULL,*oobs=NULL,*orient=NULL,*odrms=NULL;
1660 int *index=NULL,*pair=NULL,norsel=0,*orsel=NULL,*or_label=NULL;
1661 int nbounds=0,npairs;
1662 gmx_bool bDisRe,bDRAll,bORA,bORT,bODA,bODR,bODT,bORIRE,bOTEN,bDHDL;
1663 gmx_bool bFoundStart,bCont,bEDR,bVisco;
1664 double sum,sumaver,sumt,ener,dbl;
1665 double *time=NULL;
1666 real Vaver;
1667 int *set=NULL,i,j,k,nset,sss;
1668 gmx_bool *bIsEner=NULL;
1669 char **pairleg,**odtleg,**otenleg;
1670 char **leg=NULL;
1671 char **nms;
1672 char *anm_j,*anm_k,*resnm_j,*resnm_k;
1673 int resnr_j,resnr_k;
1674 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
1675 char buf[256];
1676 output_env_t oenv;
1677 t_enxblock *blk=NULL;
1678 t_enxblock *blk_disre=NULL;
1679 int ndisre=0;
1680 int dh_blocks=0, dh_hists=0, dh_samples=0, dh_lambdas=0;
1682 t_filenm fnm[] = {
1683 { efEDR, "-f", NULL, ffREAD },
1684 { efEDR, "-f2", NULL, ffOPTRD },
1685 { efTPX, "-s", NULL, ffOPTRD },
1686 { efXVG, "-o", "energy", ffWRITE },
1687 { efXVG, "-viol", "violaver",ffOPTWR },
1688 { efXVG, "-pairs","pairs", ffOPTWR },
1689 { efXVG, "-ora", "orienta", ffOPTWR },
1690 { efXVG, "-ort", "orientt", ffOPTWR },
1691 { efXVG, "-oda", "orideva", ffOPTWR },
1692 { efXVG, "-odr", "oridevr", ffOPTWR },
1693 { efXVG, "-odt", "oridevt", ffOPTWR },
1694 { efXVG, "-oten", "oriten", ffOPTWR },
1695 { efXVG, "-corr", "enecorr", ffOPTWR },
1696 { efXVG, "-vis", "visco", ffOPTWR },
1697 { efXVG, "-ravg", "runavgdf",ffOPTWR },
1698 { efXVG, "-odh", "dhdl" ,ffOPTWR }
1700 #define NFILE asize(fnm)
1701 int npargs;
1702 t_pargs *ppa;
1704 CopyRight(stderr,argv[0]);
1705 npargs = asize(pa);
1706 ppa = add_acf_pargs(&npargs,pa);
1707 parse_common_args(&argc,argv,
1708 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
1709 NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
1711 bDRAll = opt2bSet("-pairs",NFILE,fnm);
1712 bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
1713 bORA = opt2bSet("-ora",NFILE,fnm);
1714 bORT = opt2bSet("-ort",NFILE,fnm);
1715 bODA = opt2bSet("-oda",NFILE,fnm);
1716 bODR = opt2bSet("-odr",NFILE,fnm);
1717 bODT = opt2bSet("-odt",NFILE,fnm);
1718 bORIRE = bORA || bORT || bODA || bODR || bODT;
1719 bOTEN = opt2bSet("-oten",NFILE,fnm);
1720 bDHDL = opt2bSet("-odh",NFILE,fnm);
1722 nset = 0;
1724 snew(frame,2);
1725 fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
1726 do_enxnms(fp,&nre,&enm);
1728 Vaver = -1;
1730 bVisco = opt2bSet("-vis",NFILE,fnm);
1732 if (!bDisRe && !bDHDL)
1734 if (bVisco) {
1735 nset=asize(setnm);
1736 snew(set,nset);
1737 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
1738 for(j=0; j<nset; j++) {
1739 for(i=0; i<nre; i++) {
1740 if (strstr(enm[i].name,setnm[j])) {
1741 set[j]=i;
1742 break;
1745 if (i == nre) {
1746 if (gmx_strcasecmp(setnm[j],"Volume")==0) {
1747 printf("Enter the box volume (" unit_volume "): ");
1748 if(1 != scanf("%lf",&dbl))
1750 gmx_fatal(FARGS,"Error reading user input");
1752 Vaver = dbl;
1753 } else
1754 gmx_fatal(FARGS,"Could not find term %s for viscosity calculation",
1755 setnm[j]);
1759 else
1761 set=select_by_name(nre,enm,&nset);
1763 /* Print all the different units once */
1764 sprintf(buf,"(%s)",enm[set[0]].unit);
1765 for(i=1; i<nset; i++) {
1766 for(j=0; j<i; j++) {
1767 if (strcmp(enm[set[i]].unit,enm[set[j]].unit) == 0) {
1768 break;
1771 if (j == i) {
1772 strcat(buf,", (");
1773 strcat(buf,enm[set[i]].unit);
1774 strcat(buf,")");
1777 out=xvgropen(opt2fn("-o",NFILE,fnm),"Gromacs Energies","Time (ps)",buf,
1778 oenv);
1780 snew(leg,nset+1);
1781 for(i=0; (i<nset); i++)
1782 leg[i] = enm[set[i]].name;
1783 if (bSum) {
1784 leg[nset]=strdup("Sum");
1785 xvgr_legend(out,nset+1,(const char**)leg,oenv);
1787 else
1788 xvgr_legend(out,nset,(const char**)leg,oenv);
1790 snew(bIsEner,nset);
1791 for(i=0; (i<nset); i++) {
1792 bIsEner[i] = FALSE;
1793 for (j=0; (j <= F_ETOT); j++)
1794 bIsEner[i] = bIsEner[i] ||
1795 (gmx_strcasecmp(interaction_function[j].longname,leg[i]) == 0);
1798 if (bPrAll && nset > 1) {
1799 gmx_fatal(FARGS,"Printing averages can only be done when a single set is selected");
1802 time = NULL;
1804 if (bORIRE || bOTEN)
1805 get_orires_parms(ftp2fn(efTPX,NFILE,fnm),&nor,&nex,&or_label,&oobs);
1807 if (bORIRE) {
1808 if (bOrinst)
1809 enx_i = enxORI;
1810 else
1811 enx_i = enxOR;
1813 if (bORA || bODA)
1814 snew(orient,nor);
1815 if (bODR)
1816 snew(odrms,nor);
1817 if (bORT || bODT) {
1818 fprintf(stderr,"Select the orientation restraint labels you want (-1 is all)\n");
1819 fprintf(stderr,"End your selection with 0\n");
1820 j = -1;
1821 orsel = NULL;
1822 do {
1823 j++;
1824 srenew(orsel,j+1);
1825 if(1 != scanf("%d",&(orsel[j])))
1827 gmx_fatal(FARGS,"Error reading user input");
1829 } while (orsel[j] > 0);
1830 if (orsel[0] == -1) {
1831 fprintf(stderr,"Selecting all %d orientation restraints\n",nor);
1832 norsel = nor;
1833 srenew(orsel,nor);
1834 for(i=0; i<nor; i++)
1835 orsel[i] = i;
1836 } else {
1837 /* Build the selection */
1838 norsel=0;
1839 for(i=0; i<j; i++) {
1840 for(k=0; k<nor; k++)
1841 if (or_label[k] == orsel[i]) {
1842 orsel[norsel] = k;
1843 norsel++;
1844 break;
1846 if (k == nor)
1847 fprintf(stderr,"Orientation restraint label %d not found\n",
1848 orsel[i]);
1851 snew(odtleg,norsel);
1852 for(i=0; i<norsel; i++) {
1853 snew(odtleg[i],256);
1854 sprintf(odtleg[i],"%d",or_label[orsel[i]]);
1856 if (bORT) {
1857 fort=xvgropen(opt2fn("-ort",NFILE,fnm), "Calculated orientations",
1858 "Time (ps)","",oenv);
1859 if (bOrinst)
1860 fprintf(fort,"%s",orinst_sub);
1861 xvgr_legend(fort,norsel,(const char**)odtleg,oenv);
1863 if (bODT) {
1864 fodt=xvgropen(opt2fn("-odt",NFILE,fnm),
1865 "Orientation restraint deviation",
1866 "Time (ps)","",oenv);
1867 if (bOrinst)
1868 fprintf(fodt,"%s",orinst_sub);
1869 xvgr_legend(fodt,norsel,(const char**)odtleg,oenv);
1873 if (bOTEN) {
1874 foten=xvgropen(opt2fn("-oten",NFILE,fnm),
1875 "Order tensor","Time (ps)","",oenv);
1876 snew(otenleg,bOvec ? nex*12 : nex*3);
1877 for(i=0; i<nex; i++) {
1878 for(j=0; j<3; j++) {
1879 sprintf(buf,"eig%d",j+1);
1880 otenleg[(bOvec ? 12 : 3)*i+j] = strdup(buf);
1882 if (bOvec) {
1883 for(j=0; j<9; j++) {
1884 sprintf(buf,"vec%d%s",j/3+1,j%3==0 ? "x" : (j%3==1 ? "y" : "z"));
1885 otenleg[12*i+3+j] = strdup(buf);
1889 xvgr_legend(foten,bOvec ? nex*12 : nex*3,(const char**)otenleg,oenv);
1892 else if (bDisRe)
1894 nbounds=get_bounds(ftp2fn(efTPX,NFILE,fnm),&bounds,&index,&pair,&npairs,
1895 &mtop,&top,&ir);
1896 snew(violaver,npairs);
1897 out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
1898 "Time (ps)","nm",oenv);
1899 xvgr_legend(out,2,drleg,oenv);
1900 if (bDRAll) {
1901 fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
1902 "Time (ps)","Distance (nm)",oenv);
1903 if (output_env_get_print_xvgr_codes(oenv))
1904 fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
1905 ir.dr_tau);
1910 /* Initiate energies and set them to zero */
1911 edat.nsteps = 0;
1912 edat.npoints = 0;
1913 edat.nframes = 0;
1914 edat.step = NULL;
1915 edat.steps = NULL;
1916 edat.points = NULL;
1917 snew(edat.s,nset);
1919 /* Initiate counters */
1920 teller = 0;
1921 teller_disre = 0;
1922 bFoundStart = FALSE;
1923 start_step = 0;
1924 start_t = 0;
1925 do {
1926 /* This loop searches for the first frame (when -b option is given),
1927 * or when this has been found it reads just one energy frame
1929 do {
1930 bCont = do_enx(fp,&(frame[NEXT]));
1932 if (bCont) {
1933 timecheck = check_times(frame[NEXT].t);
1935 } while (bCont && (timecheck < 0));
1937 if ((timecheck == 0) && bCont) {
1938 /* We read a valid frame, so we can use it */
1939 fr = &(frame[NEXT]);
1941 if (fr->nre > 0) {
1942 /* The frame contains energies, so update cur */
1943 cur = NEXT;
1945 if (edat.nframes % 1000 == 0)
1947 srenew(edat.step,edat.nframes+1000);
1948 srenew(edat.steps,edat.nframes+1000);
1949 srenew(edat.points,edat.nframes+1000);
1950 for(i=0; i<nset; i++)
1952 srenew(edat.s[i].ener,edat.nframes+1000);
1953 srenew(edat.s[i].es ,edat.nframes+1000);
1957 nfr = edat.nframes;
1958 edat.step[nfr] = fr->step;
1960 if (!bFoundStart)
1962 bFoundStart = TRUE;
1963 /* Initiate the previous step data */
1964 start_step = fr->step;
1965 start_t = fr->t;
1966 /* Initiate the energy sums */
1967 edat.steps[nfr] = 1;
1968 edat.points[nfr] = 1;
1969 for(i=0; i<nset; i++)
1971 sss = set[i];
1972 edat.s[i].es[nfr].sum = fr->ener[sss].e;
1973 edat.s[i].es[nfr].sum2 = 0;
1975 edat.nsteps = 1;
1976 edat.npoints = 1;
1978 else
1980 edat.steps[nfr] = fr->nsteps;
1982 if (fr->step - start_step + 1 == edat.nsteps + fr->nsteps)
1984 if (fr->nsum <= 1)
1986 edat.points[nfr] = 1;
1987 for(i=0; i<nset; i++)
1989 sss = set[i];
1990 edat.s[i].es[nfr].sum = fr->ener[sss].e;
1991 edat.s[i].es[nfr].sum2 = 0;
1993 edat.npoints += 1;
1995 else
1997 edat.points[nfr] = fr->nsum;
1998 for(i=0; i<nset; i++)
2000 sss = set[i];
2001 edat.s[i].es[nfr].sum = fr->ener[sss].esum;
2002 edat.s[i].es[nfr].sum2 = fr->ener[sss].eav;
2004 edat.npoints += fr->nsum;
2007 else
2009 /* The interval does not match fr->nsteps:
2010 * can not do exact averages.
2012 edat.npoints = 0;
2014 edat.nsteps = fr->step - start_step + 1;
2017 for(i=0; i<nset; i++)
2019 edat.s[i].ener[nfr] = fr->ener[set[i]].e;
2023 * Define distance restraint legends. Can only be done after
2024 * the first frame has been read... (Then we know how many there are)
2026 blk_disre=find_block_id_enxframe(fr, enxDISRE, NULL);
2027 if (bDisRe && bDRAll && !leg && blk_disre)
2029 t_iatom *fa;
2030 t_iparams *ip;
2032 fa = top->idef.il[F_DISRES].iatoms;
2033 ip = top->idef.iparams;
2034 if (blk_disre->nsub != 2 ||
2035 (blk_disre->sub[0].nr != blk_disre->sub[1].nr) )
2037 gmx_incons("Number of disre sub-blocks not equal to 2");
2040 ndisre=blk_disre->sub[0].nr ;
2041 if (ndisre != top->idef.il[F_DISRES].nr/3)
2043 gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
2044 ndisre,top->idef.il[F_DISRES].nr/3);
2046 snew(pairleg,ndisre);
2047 for(i=0; i<ndisre; i++)
2049 snew(pairleg[i],30);
2050 j=fa[3*i+1];
2051 k=fa[3*i+2];
2052 gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
2053 gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
2054 sprintf(pairleg[i],"%d %s %d %s (%d)",
2055 resnr_j,anm_j,resnr_k,anm_k,
2056 ip[fa[3*i]].disres.label);
2058 set=select_it(ndisre,pairleg,&nset);
2059 snew(leg,2*nset);
2060 for(i=0; (i<nset); i++)
2062 snew(leg[2*i],32);
2063 sprintf(leg[2*i], "a %s",pairleg[set[i]]);
2064 snew(leg[2*i+1],32);
2065 sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
2067 xvgr_legend(fp_pairs,2*nset,(const char**)leg,oenv);
2071 * Store energies for analysis afterwards...
2073 if (!bDisRe && !bDHDL && (fr->nre > 0)) {
2074 if (edat.nframes % 1000 == 0) {
2075 srenew(time,edat.nframes+1000);
2077 time[edat.nframes] = fr->t;
2078 edat.nframes++;
2081 * Printing time, only when we do not want to skip frames
2083 if (!skip || teller % skip == 0) {
2084 if (bDisRe) {
2085 /*******************************************
2086 * D I S T A N C E R E S T R A I N T S
2087 *******************************************/
2088 if (ndisre > 0)
2090 #ifndef GMX_DOUBLE
2091 float *disre_rt = blk_disre->sub[0].fval;
2092 float *disre_rm3tav = blk_disre->sub[1].fval;
2093 #else
2094 double *disre_rt = blk_disre->sub[0].dval;
2095 double *disre_rm3tav = blk_disre->sub[1].dval;
2096 #endif
2098 print_time(out,fr->t);
2099 if (violaver == NULL)
2100 snew(violaver,ndisre);
2102 /* Subtract bounds from distances, to calculate violations */
2103 calc_violations(disre_rt, disre_rm3tav,
2104 nbounds,pair,bounds,violaver,&sumt,&sumaver);
2106 fprintf(out," %8.4f %8.4f\n",sumaver,sumt);
2107 if (bDRAll) {
2108 print_time(fp_pairs,fr->t);
2109 for(i=0; (i<nset); i++) {
2110 sss=set[i];
2111 fprintf(fp_pairs," %8.4f", mypow(disre_rm3tav[sss],minthird));
2112 fprintf(fp_pairs," %8.4f", disre_rt[sss]);
2114 fprintf(fp_pairs,"\n");
2116 teller_disre++;
2119 else if (bDHDL)
2121 do_dhdl(fr, &fp_dhdl, opt2fn("-odh",NFILE,fnm),
2122 &dh_blocks, &dh_hists, &dh_samples, &dh_lambdas,
2123 oenv);
2125 /*******************************************
2126 * E N E R G I E S
2127 *******************************************/
2128 else {
2129 if (fr->nre > 0) {
2130 if (bPrAll)
2132 /* We skip frames with single points (usually only the first frame),
2133 * since they would result in an average plot with outliers.
2135 if (fr->nsum > 1) {
2136 print_time(out,fr->t);
2137 print1(out,bDp,fr->ener[set[0]].e);
2138 print1(out,bDp,fr->ener[set[0]].esum/fr->nsum);
2139 print1(out,bDp,sqrt(fr->ener[set[0]].eav/fr->nsum));
2140 fprintf(out,"\n");
2143 else
2145 print_time(out,fr->t);
2146 if (bSum)
2148 sum = 0;
2149 for(i=0; i<nset; i++)
2151 sum += fr->ener[set[i]].e;
2153 print1(out,bDp,sum/nmol-ezero);
2155 else
2157 for(i=0; (i<nset); i++)
2159 if (bIsEner[i])
2161 print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
2163 else
2165 print1(out,bDp,fr->ener[set[i]].e);
2169 fprintf(out,"\n");
2172 #if 0
2173 /* we first count the blocks that have id 0: the orire blocks */
2174 block_orire=0;
2175 for(b=0;b<fr->nblock;b++)
2177 if (fr->block[b].id == mde_block_type_orire)
2178 nblock_orire++;
2180 #endif
2181 blk = find_block_id_enxframe(fr, enx_i, NULL);
2182 if (bORIRE && blk)
2184 #ifndef GMX_DOUBLE
2185 xdr_datatype dt=xdr_datatype_float;
2186 #else
2187 xdr_datatype dt=xdr_datatype_double;
2188 #endif
2189 real *vals;
2191 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2193 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2195 #ifndef GMX_DOUBLE
2196 vals=blk->sub[0].fval;
2197 #else
2198 vals=blk->sub[0].dval;
2199 #endif
2201 if (blk->sub[0].nr != (size_t)nor)
2202 gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)", blk->sub[0].nr);
2203 if (bORA || bODA)
2205 for(i=0; i<nor; i++)
2206 orient[i] += vals[i];
2208 if (bODR)
2210 for(i=0; i<nor; i++)
2211 odrms[i] += sqr(vals[i]-oobs[i]);
2213 if (bORT)
2215 fprintf(fort," %10f",fr->t);
2216 for(i=0; i<norsel; i++)
2217 fprintf(fort," %g",vals[orsel[i]]);
2218 fprintf(fort,"\n");
2220 if (bODT)
2222 fprintf(fodt," %10f",fr->t);
2223 for(i=0; i<norsel; i++)
2224 fprintf(fodt," %g", vals[orsel[i]]-oobs[orsel[i]]);
2225 fprintf(fodt,"\n");
2227 norfr++;
2229 blk = find_block_id_enxframe(fr, enxORT, NULL);
2230 if (bOTEN && blk)
2232 #ifndef GMX_DOUBLE
2233 xdr_datatype dt=xdr_datatype_float;
2234 #else
2235 xdr_datatype dt=xdr_datatype_double;
2236 #endif
2237 real *vals;
2239 if ( (blk->nsub != 1) || (blk->sub[0].type!=dt) )
2240 gmx_fatal(FARGS,"Orientational restraints read in incorrectly");
2241 #ifndef GMX_DOUBLE
2242 vals=blk->sub[0].fval;
2243 #else
2244 vals=blk->sub[0].dval;
2245 #endif
2247 if (blk->sub[0].nr != (size_t)(nex*12))
2248 gmx_fatal(FARGS,"Number of orientation experiments in energy file (%g) does not match with the topology (%d)",
2249 blk->sub[0].nr/12, nex);
2250 fprintf(foten," %10f",fr->t);
2251 for(i=0; i<nex; i++)
2252 for(j=0; j<(bOvec?12:3); j++)
2253 fprintf(foten," %g",vals[i*12+j]);
2254 fprintf(foten,"\n");
2259 } while (bCont && (timecheck == 0));
2261 fprintf(stderr,"\n");
2262 close_enx(fp);
2263 if (out)
2264 ffclose(out);
2266 if (bDRAll)
2267 ffclose(fp_pairs);
2269 if (bORT)
2270 ffclose(fort);
2271 if (bODT)
2272 ffclose(fodt);
2273 if (bORA)
2275 out = xvgropen(opt2fn("-ora",NFILE,fnm),
2276 "Average calculated orientations",
2277 "Restraint label","",oenv);
2278 if (bOrinst)
2279 fprintf(out,"%s",orinst_sub);
2280 for(i=0; i<nor; i++)
2281 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr);
2282 ffclose(out);
2284 if (bODA) {
2285 out = xvgropen(opt2fn("-oda",NFILE,fnm),
2286 "Average restraint deviation",
2287 "Restraint label","",oenv);
2288 if (bOrinst)
2289 fprintf(out,"%s",orinst_sub);
2290 for(i=0; i<nor; i++)
2291 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr-oobs[i]);
2292 ffclose(out);
2294 if (bODR) {
2295 out = xvgropen(opt2fn("-odr",NFILE,fnm),
2296 "RMS orientation restraint deviations",
2297 "Restraint label","",oenv);
2298 if (bOrinst)
2299 fprintf(out,"%s",orinst_sub);
2300 for(i=0; i<nor; i++)
2301 fprintf(out,"%5d %g\n",or_label[i],sqrt(odrms[i]/norfr));
2302 ffclose(out);
2304 if (bOTEN)
2305 ffclose(foten);
2307 if (bDisRe)
2309 analyse_disre(opt2fn("-viol",NFILE,fnm),
2310 teller_disre,violaver,bounds,index,pair,nbounds,oenv);
2312 else if (bDHDL)
2314 if (fp_dhdl)
2316 ffclose(fp_dhdl);
2317 printf("\n\nWrote %d lambda values with %d samples as ",
2318 dh_lambdas, dh_samples);
2319 if (dh_hists > 0)
2321 printf("%d dH histograms ", dh_hists);
2323 if (dh_blocks> 0)
2325 printf("%d dH data blocks ", dh_blocks);
2327 printf("to %s\n", opt2fn("-odh",NFILE,fnm));
2330 else
2332 gmx_fatal(FARGS, "No dH data in %s\n", opt2fn("-f",NFILE,fnm));
2336 else
2338 analyse_ener(opt2bSet("-corr",NFILE,fnm),opt2fn("-corr",NFILE,fnm),
2339 bFee,bSum,bFluct,opt2parg_bSet("-nmol",npargs,ppa),
2340 bVisco,opt2fn("-vis",NFILE,fnm),
2341 nmol,nconstr,start_step,start_t,frame[cur].step,frame[cur].t,
2342 time,reftemp,&edat,
2343 nset,set,bIsEner,leg,enm,Vaver,ezero,nbmin,nbmax,
2344 oenv);
2346 if (opt2bSet("-f2",NFILE,fnm)) {
2347 fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
2348 reftemp, nset, set, leg, &edat, time ,oenv);
2352 const char *nxy = "-nxy";
2354 do_view(oenv,opt2fn("-o",NFILE,fnm),nxy);
2355 do_view(oenv,opt2fn_null("-ravg",NFILE,fnm),nxy);
2356 do_view(oenv,opt2fn_null("-ora",NFILE,fnm),nxy);
2357 do_view(oenv,opt2fn_null("-ort",NFILE,fnm),nxy);
2358 do_view(oenv,opt2fn_null("-oda",NFILE,fnm),nxy);
2359 do_view(oenv,opt2fn_null("-odr",NFILE,fnm),nxy);
2360 do_view(oenv,opt2fn_null("-odt",NFILE,fnm),nxy);
2361 do_view(oenv,opt2fn_null("-oten",NFILE,fnm),nxy);
2362 do_view(oenv,opt2fn_null("-odh",NFILE,fnm),nxy);
2364 thanx(stderr);
2366 return 0;