Don't use POSIX fnmatch() for pattern matching.
[gromacs/qmmm-gamess-us.git] / src / tools / gmx_energy.c
blob4f141c12df295496b44ae5e28caf04734245454f
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.2.0
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
32 * And Hey:
33 * Green Red Orange Magenta Azure Cyan Skyblue
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <string.h>
40 #include <math.h>
41 #include <ctype.h>
43 #include "typedefs.h"
44 #include "gmx_fatal.h"
45 #include "vec.h"
46 #include "string2.h"
47 #include "smalloc.h"
48 #include "enxio.h"
49 #include "statutil.h"
50 #include "names.h"
51 #include "copyrite.h"
52 #include "macros.h"
53 #include "xvgr.h"
54 #include "gstat.h"
55 #include "physics.h"
56 #include "tpxio.h"
57 #include "viewit.h"
58 #include "mtop_util.h"
59 #include "gmx_statistics.h"
61 static real minthird=-1.0/3.0,minsixth=-1.0/6.0;
63 typedef struct {
64 int nframes;
65 double *sum;
66 double *sum2;
67 } enersum_t;
69 static double mypow(double x,double y)
71 if (x > 0)
72 return pow(x,y);
73 else
74 return 0.0;
77 static int *select_it(int nre,char *nm[],int *nset)
79 bool *bE;
80 int n,k,j,i;
81 int *set;
82 bool bVerbose = TRUE;
84 if ((getenv("VERBOSE")) != NULL)
85 bVerbose = FALSE;
87 fprintf(stderr,"Select the terms you want from the following list\n");
88 fprintf(stderr,"End your selection with 0\n");
90 if ( bVerbose ) {
91 for(k=0; (k<nre); ) {
92 for(j=0; (j<4) && (k<nre); j++,k++)
93 fprintf(stderr," %3d=%14s",k+1,nm[k]);
94 fprintf(stderr,"\n");
98 snew(bE,nre);
99 do {
100 if(1 != scanf("%d",&n))
102 gmx_fatal(FARGS,"Error reading user input");
104 if ((n>0) && (n<=nre))
105 bE[n-1]=TRUE;
106 } while (n != 0);
108 snew(set,nre);
109 for(i=(*nset)=0; (i<nre); i++)
110 if (bE[i])
111 set[(*nset)++]=i;
113 sfree(bE);
115 return set;
118 static int strcount(const char *s1,const char *s2)
120 int n=0;
121 while (s1 && s2 && (toupper(s1[n]) == toupper(s2[n])))
122 n++;
123 return n;
126 static void chomp(char *buf)
128 int len = strlen(buf);
130 while ((len > 0) && (buf[len-1] == '\n')) {
131 buf[len-1] = '\0';
132 len--;
136 static int *select_by_name(int nre,gmx_enxnm_t *nm,int *nset)
138 bool *bE;
139 int n,k,kk,j,i,nmatch,nind,nss;
140 int *set;
141 bool bEOF,bVerbose = TRUE,bLong=FALSE;
142 char *ptr,buf[STRLEN];
143 const char *fm4="%3d %-14s";
144 const char *fm2="%3d %-34s";
145 char **newnm=NULL;
147 if ((getenv("VERBOSE")) != NULL)
148 bVerbose = FALSE;
150 fprintf(stderr,"\n");
151 fprintf(stderr,"Select the terms you want from the following list by\n");
152 fprintf(stderr,"selecting either (part of) the name or the number or a combination.\n");
153 fprintf(stderr,"End your selection with an empty line or a zero.\n");
154 fprintf(stderr,"-------------------------------------------------------------------\n");
156 snew(newnm,nre);
157 j = 0;
158 for(k=0; k<nre; k++) {
159 newnm[k] = strdup(nm[k].name);
160 /* Insert dashes in all the names */
161 while ((ptr = strchr(newnm[k],' ')) != NULL) {
162 *ptr = '-';
164 if ( bVerbose ) {
165 if (j == 0) {
166 if (k > 0) {
167 fprintf(stderr,"\n");
169 bLong = FALSE;
170 for(kk=k; kk<k+4; kk++) {
171 if (kk < nre && strlen(nm[kk].name) > 14) {
172 bLong = TRUE;
175 } else {
176 fprintf(stderr," ");
178 if (!bLong) {
179 fprintf(stderr,fm4,k+1,newnm[k]);
180 j++;
181 if (j == 4) {
182 j = 0;
184 } else {
185 fprintf(stderr,fm2,k+1,newnm[k]);
186 j++;
187 if (j == 2) {
188 j = 0;
193 if ( bVerbose ) {
194 fprintf(stderr,"\n\n");
197 snew(bE,nre);
199 bEOF = FALSE;
200 while (!bEOF && (fgets2(buf,STRLEN-1,stdin))) {
201 /* Remove newlines */
202 chomp(buf);
204 /* Remove spaces */
205 trim(buf);
207 /* Empty line means end of input */
208 bEOF = (strlen(buf) == 0);
209 if (!bEOF) {
210 ptr = buf;
211 do {
212 if (!bEOF) {
213 /* First try to read an integer */
214 nss = sscanf(ptr,"%d",&nind);
215 if (nss == 1) {
216 /* Zero means end of input */
217 if (nind == 0) {
218 bEOF = TRUE;
219 } else if ((1<=nind) && (nind<=nre)) {
220 bE[nind-1] = TRUE;
221 } else {
222 fprintf(stderr,"number %d is out of range\n",nind);
225 else {
226 /* Now try to read a string */
227 i = strlen(ptr);
228 nmatch = 0;
229 for(nind=0; nind<nre; nind++) {
230 if (strcasecmp(newnm[nind],ptr) == 0) {
231 bE[nind] = TRUE;
232 nmatch++;
235 if (nmatch == 0) {
236 i = strlen(ptr);
237 nmatch = 0;
238 for(nind=0; nind<nre; nind++) {
239 if (strncasecmp(newnm[nind],ptr,i) == 0) {
240 bE[nind] = TRUE;
241 nmatch++;
244 if (nmatch == 0) {
245 fprintf(stderr,"String '%s' does not match anything\n",ptr);
250 /* Look for the first space, and remove spaces from there */
251 if ((ptr = strchr(ptr,' ')) != NULL) {
252 trim(ptr);
254 } while (!bEOF && (ptr && (strlen(ptr) > 0)));
258 snew(set,nre);
259 for(i=(*nset)=0; (i<nre); i++)
260 if (bE[i])
261 set[(*nset)++]=i;
263 sfree(bE);
265 if (*nset == 0)
266 gmx_fatal(FARGS,"No energy terms selected");
268 for(i=0; (i<nre); i++)
269 sfree(newnm[i]);
270 sfree(newnm);
272 return set;
275 static void get_orires_parms(const char *topnm,
276 int *nor,int *nex,int **label,real **obs)
278 gmx_mtop_t mtop;
279 gmx_localtop_t *top;
280 t_inputrec ir;
281 t_iparams *ip;
282 int natoms,i;
283 t_iatom *iatom;
284 int nb;
285 matrix box;
287 read_tpx(topnm,&ir,box,&natoms,NULL,NULL,NULL,&mtop);
288 top = gmx_mtop_generate_local_top(&mtop,&ir);
290 ip = top->idef.iparams;
291 iatom = top->idef.il[F_ORIRES].iatoms;
293 /* Count how many distance restraint there are... */
294 nb = top->idef.il[F_ORIRES].nr;
295 if (nb == 0)
296 gmx_fatal(FARGS,"No orientation restraints in topology!\n");
298 *nor = nb/3;
299 *nex = 0;
300 snew(*label,*nor);
301 snew(*obs,*nor);
302 for(i=0; i<nb; i+=3) {
303 (*label)[i/3] = ip[iatom[i]].orires.label;
304 (*obs)[i/3] = ip[iatom[i]].orires.obs;
305 if (ip[iatom[i]].orires.ex >= *nex)
306 *nex = ip[iatom[i]].orires.ex+1;
308 fprintf(stderr,"Found %d orientation restraints with %d experiments",
309 *nor,*nex);
312 static int get_bounds(const char *topnm,
313 real **bounds,int **index,int **dr_pair,int *npairs,
314 gmx_mtop_t *mtop,gmx_localtop_t **ltop,t_inputrec *ir)
316 gmx_localtop_t *top;
317 t_functype *functype;
318 t_iparams *ip;
319 int natoms,i,j,k,type,ftype,natom;
320 t_ilist *disres;
321 t_iatom *iatom;
322 real *b;
323 int *ind,*pair;
324 int nb,label1;
325 matrix box;
327 read_tpx(topnm,ir,box,&natoms,NULL,NULL,NULL,mtop);
328 snew(*ltop,1);
329 top = gmx_mtop_generate_local_top(mtop,ir);
330 *ltop = top;
332 functype = top->idef.functype;
333 ip = top->idef.iparams;
335 /* Count how many distance restraint there are... */
336 nb=top->idef.il[F_DISRES].nr;
337 if (nb == 0)
338 gmx_fatal(FARGS,"No distance restraints in topology!\n");
340 /* Allocate memory */
341 snew(b,nb);
342 snew(ind,nb);
343 snew(pair,nb+1);
345 /* Fill the bound array */
346 nb=0;
347 for(i=0; (i<top->idef.ntypes); i++) {
348 ftype = functype[i];
349 if (ftype == F_DISRES) {
351 label1 = ip[i].disres.label;
352 b[nb] = ip[i].disres.up1;
353 ind[nb] = label1;
354 nb++;
357 *bounds = b;
359 /* Fill the index array */
360 label1 = -1;
361 disres = &(top->idef.il[F_DISRES]);
362 iatom = disres->iatoms;
363 for(i=j=k=0; (i<disres->nr); ) {
364 type = iatom[i];
365 ftype = top->idef.functype[type];
366 natom = interaction_function[ftype].nratoms+1;
367 if (label1 != top->idef.iparams[type].disres.label) {
368 pair[j] = k;
369 label1 = top->idef.iparams[type].disres.label;
370 j ++;
372 k++;
373 i += natom;
375 pair[j] = k;
376 *npairs = k;
377 if (j != nb)
378 gmx_incons("get_bounds for distance restraints");
380 *index = ind;
381 *dr_pair = pair;
383 return nb;
386 static void calc_violations(real rt[],real rav3[],int nb,int index[],
387 real bounds[],real *viol,double *st,double *sa)
389 const real sixth=1.0/6.0;
390 int i,j;
391 double rsum,rav,sumaver,sumt;
393 sumaver = 0;
394 sumt = 0;
395 for(i=0; (i<nb); i++) {
396 rsum = 0.0;
397 rav = 0.0;
398 for(j=index[i]; (j<index[i+1]); j++) {
399 if (viol)
400 viol[j] += mypow(rt[j],-3.0);
401 rav += sqr(rav3[j]);
402 rsum += mypow(rt[j],-6);
404 rsum = max(0.0,mypow(rsum,-sixth)-bounds[i]);
405 rav = max(0.0,mypow(rav, -sixth)-bounds[i]);
407 sumt += rsum;
408 sumaver += rav;
410 *st = sumt;
411 *sa = sumaver;
414 static void analyse_disre(const char *voutfn, int nframes,
415 real violaver[], real bounds[], int index[],
416 int pair[], int nbounds,
417 const output_env_t oenv)
419 FILE *vout;
420 double sum,sumt,sumaver;
421 int i,j;
423 /* Subtract bounds from distances, to calculate violations */
424 calc_violations(violaver,violaver,
425 nbounds,pair,bounds,NULL,&sumt,&sumaver);
427 #ifdef DEBUG
428 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
429 sumaver);
430 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",
431 sumt);
432 #endif
433 vout=xvgropen(voutfn,"r\\S-3\\N average violations","DR Index","nm",
434 oenv);
435 sum = 0.0;
436 sumt = 0.0;
437 for(i=0; (i<nbounds); i++) {
438 /* Do ensemble averaging */
439 sumaver = 0;
440 for(j=pair[i]; (j<pair[i+1]); j++)
441 sumaver += sqr(violaver[j]/nframes);
442 sumaver = max(0.0,mypow(sumaver,minsixth)-bounds[i]);
444 sumt += sumaver;
445 sum = max(sum,sumaver);
446 fprintf(vout,"%10d %10.5e\n",index[i],sumaver);
448 #ifdef DEBUG
449 for(j=0; (j<dr.ndr); j++)
450 fprintf(vout,"%10d %10.5e\n",j,mypow(violaver[j]/nframes,minthird));
451 #endif
452 ffclose(vout);
454 fprintf(stdout,"\nSum of violations averaged over simulation: %g nm\n",
455 sumt);
456 fprintf(stdout,"Largest violation averaged over simulation: %g nm\n\n",sum);
458 do_view(oenv,voutfn,"-graphtype bar");
461 static void einstein_visco(const char *fn,const char *fni,int nsets,
462 int nframes,real **sum,
463 real V,real T,int nsteps,double time[],
464 const output_env_t oenv)
466 FILE *fp0,*fp1;
467 double av[4],avold[4];
468 double fac,dt,di;
469 int i,j,m,nf4;
471 if (nframes < 1)
472 return;
474 dt = (time[1]-time[0]);
475 nf4 = nframes/4+1;
477 for(i=0; i<=nsets; i++)
478 avold[i] = 0;
479 fp0=xvgropen(fni,"Shear viscosity integral",
480 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N ps)",oenv);
481 fp1=xvgropen(fn,"Shear viscosity using Einstein relation",
482 "Time (ps)","(kg m\\S-1\\N s\\S-1\\N)",oenv);
483 for(i=1; i<nf4; i++) {
484 fac = dt*nframes/nsteps;
485 for(m=0; m<=nsets; m++)
486 av[m] = 0;
487 for(j=0; j<nframes-i; j++) {
488 for(m=0; m<nsets; m++) {
489 di = sqr(fac*(sum[m][j+i]-sum[m][j]));
491 av[m] += di;
492 av[nsets] += di/nsets;
495 /* Convert to SI for the viscosity */
496 fac = (V*NANO*NANO*NANO*PICO*1e10)/(2*BOLTZMANN*T)/(nframes-i);
497 fprintf(fp0,"%10g",time[i]-time[0]);
498 for(m=0; (m<=nsets); m++) {
499 av[m] = fac*av[m];
500 fprintf(fp0," %10g",av[m]);
502 fprintf(fp0,"\n");
503 fprintf(fp1,"%10g",0.5*(time[i]+time[i-1])-time[0]);
504 for(m=0; (m<=nsets); m++) {
505 fprintf(fp1," %10g",(av[m]-avold[m])/dt);
506 avold[m] = av[m];
508 fprintf(fp1,"\n");
510 fclose(fp0);
511 fclose(fp1);
514 static void analyse_ener(bool bCorr,const char *corrfn,
515 bool bFee,bool bSum,bool bFluct,
516 bool bVisco,const char *visfn,int nmol,int ndf,
517 gmx_large_int_t start_step,double start_t,
518 gmx_large_int_t step,double t,
519 double time[], real reftemp,
520 gmx_large_int_t ee_nsum,
521 t_energy ee_sum[],enersum_t *enersum,
522 int nset,int set[],int nenergy,real **eneset,
523 real **enesum,
524 char **leg,gmx_enxnm_t *enm,
525 real Vaver,real ezero, const output_env_t oenv)
527 FILE *fp;
528 /* Check out the printed manual for equations! */
529 double Dt,aver,avertot,stddev,delta_t,totaldrift;
530 real a,b,r;
531 real xxx,integral,intBulk;
532 real sfrac,oldfrac,diffsum,diffav,fstep,pr_aver,pr_stddev,fluct2;
533 double beta=0,expE,expEtot,*fee=NULL;
534 gmx_large_int_t nsteps;
535 int nexact,nnotexact,iset;
536 double x1m,x1mk;
537 real Temp=-1,Pres=-1,VarV=-1,VarT=-1;
538 int i,j;
539 real chi2;
540 bool bIsEner;
541 char buf[256];
543 nsteps = step - start_step + 1;
544 if (nsteps < 1) {
545 fprintf(stdout,"Not enough steps (%s) for statistics\n",
546 gmx_step_str(nsteps,buf));
548 else {
549 /* Calculate the time difference */
550 delta_t = t - start_t;
552 fprintf(stdout,"\nStatistics over %s steps [ %.4f thru %.4f ps ], %d data sets\n",
553 gmx_step_str(nsteps,buf),start_t,t,nset);
555 if (ee_nsum == 0) {
556 nexact = 0;
557 nnotexact = nset;
558 } else {
559 nexact = 0;
560 nnotexact = 0;
561 for(i=0; (i<nset); i++) {
562 if (ee_sum[set[i]].esum != 0) {
563 nexact++;
564 } else {
565 nnotexact++;
570 if (nnotexact == 0) {
571 fprintf(stdout,"All averages are over %s frames\n",
572 gmx_step_str(ee_nsum,buf));
573 } else if (nexact == 0 || ee_nsum == enersum->nframes) {
574 fprintf(stdout,"All averages are over %d frames\n",enersum->nframes);
575 } else {
576 fprintf(stdout,"The term%s",nnotexact==1 ? "" : "s");
577 for(i=0; (i<nset); i++) {
578 if (ee_sum[set[i]].esum == 0) {
579 fprintf(stdout," '%s'",leg[i]);
582 fprintf(stdout," %s averaged over %d frames\n",
583 nnotexact==1 ? "is" : "are",enersum->nframes);
584 fprintf(stdout,"All other averages are over %s frames\n",
585 gmx_step_str(ee_nsum,buf));
587 fprintf(stdout,"\n");
589 fprintf(stdout,"%-24s %10s %10s %10s %10s",
590 "Energy","Average","RMSD","Fluct.","Tot-Drift");
591 if (bFee)
592 fprintf(stdout," %10s\n","-kT ln<e^(E/kT)>");
593 else
594 fprintf(stdout,"\n");
595 fprintf(stdout,"-------------------------------------------------------------------------------\n");
597 /* Initiate locals, only used with -sum */
598 avertot=0;
599 expEtot=0;
600 if (bFee) {
601 beta = 1.0/(BOLTZ*reftemp);
602 snew(fee,nset);
604 for(i=0; (i<nset); i++) {
605 iset = set[i];
606 if (ee_nsum > 0 && ee_sum[iset].esum != 0) {
607 /* We have exact sums over all the MD steps */
608 aver = ee_sum[iset].esum/ee_nsum;
609 stddev = sqrt(ee_sum[iset].eav/ee_nsum);
610 } else {
611 /* We only have data at energy file frame steps */
612 aver = enersum->sum[i]/enersum->nframes;
613 if (enersum->nframes > 1) {
614 stddev = sqrt(enersum->sum2[i]/enersum->nframes - aver*aver);
615 } else {
616 stddev = 0;
620 if (bSum)
621 avertot+=aver;
622 if (bFee) {
623 expE = 0;
624 for(j=0; (j<nenergy); j++) {
625 expE += exp(beta*(eneset[i][j]-aver)/nmol);
627 if (bSum)
628 expEtot+=expE/nenergy;
630 fee[i] = log(expE/nenergy)/beta + aver/nmol;
632 if (strstr(leg[i],"empera") != NULL) {
633 VarT = sqr(stddev);
634 Temp = aver;
635 } else if (strstr(leg[i],"olum") != NULL) {
636 VarV = sqr(stddev);
637 Vaver= aver;
638 } else if (strstr(leg[i],"essure") != NULL) {
639 Pres = aver;
641 bIsEner = FALSE;
642 for (j=0; (j <= F_ETOT); j++)
643 bIsEner = bIsEner ||
644 (strcasecmp(interaction_function[j].longname,leg[i]) == 0);
645 if (bIsEner) {
646 pr_aver = aver/nmol-ezero;
647 pr_stddev = stddev/nmol;
649 else {
650 pr_aver = aver;
651 pr_stddev = stddev;
653 if (nenergy > 1) {
654 lsq_y_ax_b_xdouble(nenergy,time,eneset[i],&a,&b,&r,&chi2);
655 totaldrift = a * delta_t;
656 } else {
657 totaldrift = 0;
659 fluct2 = sqr(pr_stddev) - sqr(totaldrift)/12;
660 if (fluct2 < 0)
661 fluct2 = 0;
662 fprintf(stdout,"%-24s %10g %10g %10g %10g",
663 leg[i],pr_aver,pr_stddev,sqrt(fluct2),totaldrift);
664 if (bFee)
665 fprintf(stdout," %10g",fee[i]);
667 fprintf(stdout," (%s)\n",enm[set[i]].unit);
669 if (bFluct) {
670 for(j=0; (j<nenergy); j++)
671 eneset[i][j] -= aver;
674 if (bSum) {
675 fprintf(stdout,"%-24s %10g %10s %10s %10s %10s",
676 "Total",avertot/nmol,"--","--","--","--");
677 /* pr_aver,pr_stddev,a,totaldrift */
678 if (bFee)
679 fprintf(stdout," %10g %10g\n",
680 log(expEtot)/beta + avertot/nmol,log(expEtot)/beta);
681 else
682 fprintf(stdout,"\n");
684 if (Temp != -1) {
685 real factor;
687 factor = nmol*ndf*VarT/(3.0*sqr(Temp));
688 fprintf(stdout,"Heat Capacity Cv: %10g J/mol K (factor = %g)\n",
689 1000*BOLTZ/(2.0/3.0 - factor),factor);
691 if ((VarV != -1) && (Temp != -1)) {
692 real tmp = VarV/(Vaver*BOLTZ*Temp*PRESFAC);
694 fprintf(stdout,"Isothermal Compressibility: %10g /%s\n",
695 tmp,unit_pres_bar);
696 fprintf(stdout,"Adiabatic bulk modulus: %10g %s\n",
697 1.0/tmp,unit_pres_bar);
699 /* Do correlation function */
700 Dt = delta_t/nenergy;
701 if (bVisco) {
702 char *leg[] = { "Shear", "Bulk" };
703 real factor;
705 /* Assume pressure tensor is in Pxx Pxy Pxz Pyx Pyy Pyz Pzx Pzy Pzz */
707 /* Symmetrise tensor! (and store in first three elements)
708 * And subtract average pressure!
710 for(i=0; (i<nenergy); i++) {
711 eneset[0][i] = 0.5*(eneset[1][i]+eneset[3][i]);
712 eneset[1][i] = 0.5*(eneset[2][i]+eneset[6][i]);
713 eneset[2][i] = 0.5*(eneset[5][i]+eneset[7][i]);
714 eneset[11][i] -= Pres;
715 enesum[0][i] = 0.5*(enesum[1][i]+enesum[3][i]);
716 enesum[1][i] = 0.5*(enesum[2][i]+enesum[6][i]);
717 enesum[2][i] = 0.5*(enesum[5][i]+enesum[7][i]);
720 einstein_visco("evisco.xvg","eviscoi.xvg",
721 3,nenergy,enesum,Vaver,Temp,nsteps,time,oenv);
723 /*do_autocorr(corrfn,buf,nenergy,3,eneset,Dt,eacNormal,TRUE);*/
724 /* Do it for shear viscosity */
725 strcpy(buf,"Shear Viscosity");
726 low_do_autocorr(corrfn,oenv,buf,nenergy,3,(nenergy+1)/2,eneset,Dt,
727 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
729 /* Now for bulk viscosity */
730 strcpy(buf,"Bulk Viscosity");
731 low_do_autocorr(corrfn,oenv,buf,nenergy,1,(nenergy+1)/2,&(eneset[11]),Dt,
732 eacNormal,1,TRUE,FALSE,FALSE,0.0,0.0,0,1);
734 factor = (Vaver*1e-26/(BOLTZMANN*Temp))*Dt;
735 fp=xvgropen(visfn,buf,"Time (ps)","\\8h\\4 (cp)",oenv);
736 xvgr_legend(fp,asize(leg),leg,oenv);
738 /* Use trapezium rule for integration */
739 integral = 0;
740 intBulk = 0;
741 for(i=1; (i<nenergy/2); i++) {
742 integral += 0.5*(eneset[0][i-1] + eneset[0][i])*factor;
743 intBulk += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
744 fprintf(fp,"%10g %10g %10g\n",(i*Dt),integral,intBulk);
746 fclose(fp);
748 else if (bCorr) {
749 if (bFluct)
750 strcpy(buf,"Autocorrelation of Energy Fluctuations");
751 else
752 strcpy(buf,"Energy Autocorrelation");
753 do_autocorr(corrfn,oenv,buf,nenergy,
754 bSum ? 1 : nset,
755 bSum ? &(eneset[nset-1]) : eneset,
756 (delta_t/nenergy),eacNormal,FALSE);
761 static void print_time(FILE *fp,double t)
763 fprintf(fp,"%12.6f",t);
766 static void print1(FILE *fp,bool bDp,real e)
768 if (bDp)
769 fprintf(fp," %16.12f",e);
770 else
771 fprintf(fp," %10.6f",e);
775 static void fec(const char *ene2fn, const char *runavgfn,
776 real reftemp, int nset, int set[], char *leg[],
777 int nenergy, real **eneset, double time[],
778 const output_env_t oenv)
780 char *ravgleg[] = { "\\8D\\4E = E\\sB\\N-E\\sA\\N",
781 "<e\\S-\\8D\\4E/kT\\N>\\s0..t\\N" };
782 FILE *fp;
783 ener_file_t enx;
784 int nre,timecheck,step,nenergy2,maxenergy;
785 int i,j;
786 bool bCont;
787 real aver, beta;
788 real **eneset2;
789 double dE, sum;
790 gmx_enxnm_t *enm=NULL;
791 t_enxframe *fr;
792 char buf[22];
794 /* read second energy file */
795 snew(fr,1);
796 enm = NULL;
797 enx = open_enx(ene2fn,"r");
798 do_enxnms(enx,&(fr->nre),&enm);
800 snew(eneset2,nset+1);
801 nenergy2=0;
802 maxenergy=0;
803 timecheck=0;
804 do {
805 /* This loop searches for the first frame (when -b option is given),
806 * or when this has been found it reads just one energy frame
808 do {
809 bCont = do_enx(enx,fr);
811 if (bCont)
812 timecheck = check_times(fr->t);
814 } while (bCont && (timecheck < 0));
816 /* Store energies for analysis afterwards... */
817 if ((timecheck == 0) && bCont) {
818 if (fr->nre > 0) {
819 if ( nenergy2 >= maxenergy ) {
820 maxenergy += 1000;
821 for(i=0; i<=nset; i++)
822 srenew(eneset2[i],maxenergy);
824 if (fr->t != time[nenergy2])
825 fprintf(stderr,"\nWARNING time mismatch %g!=%g at frame %s\n",
826 fr->t, time[nenergy2], gmx_step_str(fr->step,buf));
827 for(i=0; i<nset; i++)
828 eneset2[i][nenergy2] = fr->ener[set[i]].e;
829 nenergy2++;
832 } while (bCont && (timecheck == 0));
834 /* check */
835 if(nenergy!=nenergy2)
836 fprintf(stderr,"\nWARNING file length mismatch %d!=%d\n",nenergy,nenergy2);
837 nenergy=min(nenergy,nenergy2);
839 /* calculate fe difference dF = -kT ln < exp(-(E_B-E_A)/kT) >_A */
840 fp=NULL;
841 if (runavgfn) {
842 fp=xvgropen(runavgfn,"Running average free energy difference",
843 "Time (" unit_time ")","\\8D\\4E (" unit_energy ")",oenv);
844 xvgr_legend(fp,asize(ravgleg),ravgleg,oenv);
846 fprintf(stdout,"\n%-24s %10s\n",
847 "Energy","dF = -kT ln < exp(-(EB-EA)/kT) >A");
848 sum=0;
849 beta = 1.0/(BOLTZ*reftemp);
850 for(i=0; i<nset; i++) {
851 if (strcasecmp(leg[i],enm[set[i]].name)!=0)
852 fprintf(stderr,"\nWARNING energy set name mismatch %s!=%s\n",
853 leg[i],enm[set[i]].name);
854 for(j=0; j<nenergy; j++) {
855 dE = eneset2[i][j]-eneset[i][j];
856 sum += exp(-dE*beta);
857 if (fp)
858 fprintf(fp,"%10g %10g %10g\n",
859 time[j], dE, -BOLTZ*reftemp*log(sum/(j+1)) );
861 aver = -BOLTZ*reftemp*log(sum/nenergy);
862 fprintf(stdout,"%-24s %10g\n",leg[i],aver);
864 if(fp) ffclose(fp);
865 sfree(fr);
868 int gmx_energy(int argc,char *argv[])
870 const char *desc[] = {
872 "g_energy extracts energy components or distance restraint",
873 "data from an energy file. The user is prompted to interactively",
874 "select the energy terms she wants.[PAR]",
876 "Average and RMSD are calculated with full precision from the",
877 "simulation (see printed manual). Drift is calculated by performing",
878 "a LSQ fit of the data to a straight line. The reported total drift",
879 "is the difference of the fit at the first and last point.",
880 "The term fluctuation gives the RMSD around the LSQ fit.[PAR]",
882 "When the [TT]-viol[tt] option is set, the time averaged",
883 "violations are plotted and the running time-averaged and",
884 "instantaneous sum of violations are recalculated. Additionally",
885 "running time-averaged and instantaneous distances between",
886 "selected pairs can be plotted with the [TT]-pairs[tt] option.[PAR]",
888 "Options [TT]-ora[tt], [TT]-ort[tt], [TT]-oda[tt], [TT]-odr[tt] and",
889 "[TT]-odt[tt] are used for analyzing orientation restraint data.",
890 "The first two options plot the orientation, the last three the",
891 "deviations of the orientations from the experimental values.",
892 "The options that end on an 'a' plot the average over time",
893 "as a function of restraint. The options that end on a 't'",
894 "prompt the user for restraint label numbers and plot the data",
895 "as a function of time. Option [TT]-odr[tt] plots the RMS",
896 "deviation as a function of restraint.",
897 "When the run used time or ensemble averaged orientation restraints,",
898 "option [TT]-orinst[tt] can be used to analyse the instantaneous,",
899 "not ensemble-averaged orientations and deviations instead of",
900 "the time and ensemble averages.[PAR]",
902 "Option [TT]-oten[tt] plots the eigenvalues of the molecular order",
903 "tensor for each orientation restraint experiment. With option",
904 "[TT]-ovec[tt] also the eigenvectors are plotted.[PAR]",
906 "With [TT]-fee[tt] an estimate is calculated for the free-energy",
907 "difference with an ideal gas state: [BR]",
908 " Delta A = A(N,V,T) - A_idgas(N,V,T) = kT ln < e^(Upot/kT) >[BR]",
909 " Delta G = G(N,p,T) - G_idgas(N,p,T) = kT ln < e^(Upot/kT) >[BR]",
910 "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and"
911 "the average is over the ensemble (or time in a trajectory).",
912 "Note that this is in principle",
913 "only correct when averaging over the whole (Boltzmann) ensemble",
914 "and using the potential energy. This also allows for an entropy",
915 "estimate using:[BR]",
916 " Delta S(N,V,T) = S(N,V,T) - S_idgas(N,V,T) = (<Upot> - Delta A)/T[BR]",
917 " Delta S(N,p,T) = S(N,p,T) - S_idgas(N,p,T) = (<Upot> + pV - Delta G)/T",
918 "[PAR]",
920 "When a second energy file is specified ([TT]-f2[tt]), a free energy",
921 "difference is calculated dF = -kT ln < e ^ -(EB-EA)/kT >A ,",
922 "where EA and EB are the energies from the first and second energy",
923 "files, and the average is over the ensemble A. [BB]NOTE[bb] that",
924 "the energies must both be calculated from the same trajectory."
927 static bool bSum=FALSE,bFee=FALSE,bAll=FALSE,bFluct=FALSE;
928 static bool bDp=FALSE,bMutot=FALSE,bOrinst=FALSE,bOvec=FALSE;
929 static int skip=0,nmol=1,ndf=3;
930 static real reftemp=300.0,ezero=0;
931 t_pargs pa[] = {
932 { "-fee", FALSE, etBOOL, {&bFee},
933 "Do a free energy estimate" },
934 { "-fetemp", FALSE, etREAL,{&reftemp},
935 "Reference temperature for free energy calculation" },
936 { "-zero", FALSE, etREAL, {&ezero},
937 "Subtract a zero-point energy" },
938 { "-sum", FALSE, etBOOL, {&bSum},
939 "Sum the energy terms selected rather than display them all" },
940 { "-dp", FALSE, etBOOL, {&bDp},
941 "Print energies in high precision" },
942 { "-mutot",FALSE, etBOOL, {&bMutot},
943 "Compute the total dipole moment from the components" },
944 { "-skip", FALSE, etINT, {&skip},
945 "Skip number of frames between data points" },
946 { "-aver", FALSE, etBOOL, {&bAll},
947 "Print also the X1,t and sigma1,t, only if only 1 energy is requested" },
948 { "-nmol", FALSE, etINT, {&nmol},
949 "Number of molecules in your sample: the energies are divided by this number" },
950 { "-ndf", FALSE, etINT, {&ndf},
951 "Number of degrees of freedom per molecule. Necessary for calculating the heat capacity" },
952 { "-fluc", FALSE, etBOOL, {&bFluct},
953 "Calculate autocorrelation of energy fluctuations rather than energy itself" },
954 { "-orinst", FALSE, etBOOL, {&bOrinst},
955 "Analyse instantaneous orientation data" },
956 { "-ovec", FALSE, etBOOL, {&bOvec},
957 "Also plot the eigenvectors with -oten" }
959 char *drleg[] = {
960 "Running average",
961 "Instantaneous"
963 static const char *setnm[] = {
964 "Pres-XX", "Pres-XY", "Pres-XZ", "Pres-YX", "Pres-YY",
965 "Pres-YZ", "Pres-ZX", "Pres-ZY", "Pres-ZZ", "Temperature",
966 "Volume", "Pressure"
969 FILE *out,*fp_pairs=NULL,*fort=NULL,*fodt=NULL,*foten=NULL;
970 FILE **drout;
971 ener_file_t fp;
972 int timecheck=0;
973 gmx_mtop_t mtop;
974 gmx_localtop_t *top=NULL;
975 t_inputrec ir;
976 t_energy *ee_sum,**ee;
977 enersum_t enersum;
978 gmx_enxnm_t *enm=NULL;
979 t_enxframe *frame,*fr=NULL;
980 int cur=0;
981 #define NEXT (1-cur)
982 int nre,teller,teller_disre;
983 gmx_large_int_t start_step,ee_nsteps,ee_nsum;
984 int nor=0,nex=0,norfr=0,enx_i=0;
985 real start_t;
986 real *bounds=NULL,*violaver=NULL,*oobs=NULL,*orient=NULL,*odrms=NULL;
987 int *index=NULL,*pair=NULL,norsel=0,*orsel=NULL,*or_label=NULL;
988 int nbounds=0,npairs;
989 bool bDisRe,bDRAll,bORA,bORT,bODA,bODR,bODT,bORIRE,bOTEN;
990 bool bFoundStart,bCont,bEDR,bVisco;
991 double sum,sumaver,sumt,ener,dbl;
992 double *time=NULL;
993 real **eneset=NULL, **enesum=NULL,Vaver;
994 int *set=NULL,i,j,k,nset,sss,nenergy;
995 char **pairleg,**odtleg,**otenleg;
996 char **leg=NULL;
997 char **nms;
998 char *anm_j,*anm_k,*resnm_j,*resnm_k;
999 int resnr_j,resnr_k;
1000 const char *orinst_sub = "@ subtitle \"instantaneous\"\n";
1001 char buf[256];
1002 output_env_t oenv;
1003 t_filenm fnm[] = {
1004 { efEDR, "-f", NULL, ffREAD },
1005 { efEDR, "-f2", NULL, ffOPTRD },
1006 { efTPX, "-s", NULL, ffOPTRD },
1007 { efXVG, "-o", "energy", ffWRITE },
1008 { efXVG, "-viol", "violaver",ffOPTWR },
1009 { efXVG, "-pairs","pairs", ffOPTWR },
1010 { efXVG, "-ora", "orienta", ffOPTWR },
1011 { efXVG, "-ort", "orientt", ffOPTWR },
1012 { efXVG, "-oda", "orideva", ffOPTWR },
1013 { efXVG, "-odr", "oridevr", ffOPTWR },
1014 { efXVG, "-odt", "oridevt", ffOPTWR },
1015 { efXVG, "-oten", "oriten", ffOPTWR },
1016 { efXVG, "-corr", "enecorr", ffOPTWR },
1017 { efXVG, "-vis", "visco", ffOPTWR },
1018 { efXVG, "-ravg", "runavgdf",ffOPTWR }
1020 #define NFILE asize(fnm)
1021 int npargs;
1022 t_pargs *ppa;
1024 CopyRight(stderr,argv[0]);
1025 npargs = asize(pa);
1026 ppa = add_acf_pargs(&npargs,pa);
1027 parse_common_args(&argc,argv,
1028 PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_BE_NICE,
1029 NFILE,fnm,npargs,ppa,asize(desc),desc,0,NULL,&oenv);
1031 bDRAll = opt2bSet("-pairs",NFILE,fnm);
1032 bDisRe = opt2bSet("-viol",NFILE,fnm) || bDRAll;
1033 bORA = opt2bSet("-ora",NFILE,fnm);
1034 bORT = opt2bSet("-ort",NFILE,fnm);
1035 bODA = opt2bSet("-oda",NFILE,fnm);
1036 bODR = opt2bSet("-odr",NFILE,fnm);
1037 bODT = opt2bSet("-odt",NFILE,fnm);
1038 bORIRE = bORA || bORT || bODA || bODR || bODT;
1039 bOTEN = opt2bSet("-oten",NFILE,fnm);
1041 nset = 0;
1043 snew(frame,2);
1044 fp = open_enx(ftp2fn(efEDR,NFILE,fnm),"r");
1045 do_enxnms(fp,&nre,&enm);
1047 /* Initiate energies and set them to zero */
1048 snew(ee_sum,nre);
1049 enersum.nframes = 0;
1050 snew(enersum.sum,nre);
1051 snew(enersum.sum2,nre);
1052 nenergy = 0;
1053 Vaver = -1;
1055 bVisco = opt2bSet("-vis",NFILE,fnm);
1057 if (!bDisRe) {
1058 if (bVisco) {
1059 nset=asize(setnm);
1060 snew(set,nset);
1061 /* This is nasty code... To extract Pres tensor, Volume and Temperature */
1062 for(j=0; j<nset; j++) {
1063 for(i=0; i<nre; i++) {
1064 if (strstr(enm[i].name,setnm[j])) {
1065 set[j]=i;
1066 break;
1069 if (i == nre) {
1070 if (strcasecmp(setnm[j],"Volume")==0) {
1071 printf("Enter the box volume (" unit_volume "): ");
1072 if(1 != scanf("%lf",&dbl))
1074 gmx_fatal(FARGS,"Error reading user input");
1076 Vaver = dbl;
1077 } else
1078 gmx_fatal(FARGS,"Could not find term %s for viscosity calculation",
1079 setnm[j]);
1083 else {
1084 set=select_by_name(nre,enm,&nset);
1086 /* Print all the different units once */
1087 sprintf(buf,"(%s)",enm[set[0]].unit);
1088 for(i=1; i<nset; i++) {
1089 for(j=0; j<i; j++) {
1090 if (strcmp(enm[set[i]].unit,enm[set[j]].unit) == 0) {
1091 break;
1094 if (j == i) {
1095 strcat(buf,", (");
1096 strcat(buf,enm[set[i]].unit);
1097 strcat(buf,")");
1100 out=xvgropen(opt2fn("-o",NFILE,fnm),"Gromacs Energies","Time (ps)",buf,
1101 oenv);
1103 snew(leg,nset+1);
1104 for(i=0; (i<nset); i++)
1105 leg[i] = enm[set[i]].name;
1106 if (bSum) {
1107 leg[nset]=strdup("Sum");
1108 xvgr_legend(out,nset+1,leg,oenv);
1110 else
1111 xvgr_legend(out,nset,leg,oenv);
1113 snew(eneset,nset+1);
1114 if (bVisco)
1115 snew(enesum,nset+1);
1116 time = NULL;
1118 if (bORIRE || bOTEN)
1119 get_orires_parms(ftp2fn(efTPX,NFILE,fnm),&nor,&nex,&or_label,&oobs);
1121 if (bORIRE) {
1122 if (bOrinst)
1123 enx_i = enxORI;
1124 else
1125 enx_i = enxOR;
1127 if (bORA || bODA)
1128 snew(orient,nor);
1129 if (bODR)
1130 snew(odrms,nor);
1131 if (bORT || bODT) {
1132 fprintf(stderr,"Select the orientation restraint labels you want (-1 is all)\n");
1133 fprintf(stderr,"End your selection with 0\n");
1134 j = -1;
1135 orsel = NULL;
1136 do {
1137 j++;
1138 srenew(orsel,j+1);
1139 if(1 != scanf("%d",&(orsel[j])))
1141 gmx_fatal(FARGS,"Error reading user input");
1143 } while (orsel[j] > 0);
1144 if (orsel[0] == -1) {
1145 fprintf(stderr,"Selecting all %d orientation restraints\n",nor);
1146 norsel = nor;
1147 srenew(orsel,nor);
1148 for(i=0; i<nor; i++)
1149 orsel[i] = i;
1150 } else {
1151 /* Build the selection */
1152 norsel=0;
1153 for(i=0; i<j; i++) {
1154 for(k=0; k<nor; k++)
1155 if (or_label[k] == orsel[i]) {
1156 orsel[norsel] = k;
1157 norsel++;
1158 break;
1160 if (k == nor)
1161 fprintf(stderr,"Orientation restraint label %d not found\n",
1162 orsel[i]);
1165 snew(odtleg,norsel);
1166 for(i=0; i<norsel; i++) {
1167 snew(odtleg[i],256);
1168 sprintf(odtleg[i],"%d",or_label[orsel[i]]);
1170 if (bORT) {
1171 fort=xvgropen(opt2fn("-ort",NFILE,fnm), "Calculated orientations",
1172 "Time (ps)","",oenv);
1173 if (bOrinst)
1174 fprintf(fort,"%s",orinst_sub);
1175 xvgr_legend(fort,norsel,odtleg,oenv);
1177 if (bODT) {
1178 fodt=xvgropen(opt2fn("-odt",NFILE,fnm),
1179 "Orientation restraint deviation",
1180 "Time (ps)","",oenv);
1181 if (bOrinst)
1182 fprintf(fodt,"%s",orinst_sub);
1183 xvgr_legend(fodt,norsel,odtleg,oenv);
1187 if (bOTEN) {
1188 foten=xvgropen(opt2fn("-oten",NFILE,fnm),
1189 "Order tensor","Time (ps)","",oenv);
1190 snew(otenleg,bOvec ? nex*12 : nex*3);
1191 for(i=0; i<nex; i++) {
1192 for(j=0; j<3; j++) {
1193 sprintf(buf,"eig%d",j+1);
1194 otenleg[(bOvec ? 12 : 3)*i+j] = strdup(buf);
1196 if (bOvec) {
1197 for(j=0; j<9; j++) {
1198 sprintf(buf,"vec%d%s",j/3+1,j%3==0 ? "x" : (j%3==1 ? "y" : "z"));
1199 otenleg[12*i+3+j] = strdup(buf);
1203 xvgr_legend(foten,bOvec ? nex*12 : nex*3,otenleg,oenv);
1206 else {
1207 nbounds=get_bounds(ftp2fn(efTPX,NFILE,fnm),&bounds,&index,&pair,&npairs,
1208 &mtop,&top,&ir);
1209 snew(violaver,npairs);
1210 out=xvgropen(opt2fn("-o",NFILE,fnm),"Sum of Violations",
1211 "Time (ps)","nm",oenv);
1212 xvgr_legend(out,2,drleg,oenv);
1213 if (bDRAll) {
1214 fp_pairs=xvgropen(opt2fn("-pairs",NFILE,fnm),"Pair Distances",
1215 "Time (ps)","Distance (nm)",oenv);
1216 if (get_print_xvgr_codes(oenv))
1217 fprintf(fp_pairs,"@ subtitle \"averaged (tau=%g) and instantaneous\"\n",
1218 ir.dr_tau);
1222 /* Initiate counters */
1223 teller = 0;
1224 teller_disre = 0;
1225 bFoundStart = FALSE;
1226 start_step = 0;
1227 start_t = 0;
1228 ee_nsteps = 0;
1229 ee_nsum = 0;
1230 do {
1231 /* This loop searches for the first frame (when -b option is given),
1232 * or when this has been found it reads just one energy frame
1234 do {
1235 bCont = do_enx(fp,&(frame[NEXT]));
1237 if (bCont) {
1238 timecheck = check_times(frame[NEXT].t);
1240 } while (bCont && (timecheck < 0));
1242 if ((timecheck == 0) && bCont) {
1243 /* We read a valid frame, so we can use it */
1244 fr = &(frame[NEXT]);
1246 if (fr->nre > 0) {
1247 /* The frame contains energies, so update cur */
1248 cur = NEXT;
1250 if (!bFoundStart) {
1251 bFoundStart = TRUE;
1252 /* Initiate the previous step data */
1253 start_step = fr->step;
1254 start_t = fr->t;
1255 /* Initiate the energy sums */
1256 for(i=0; i<fr->nre; i++) {
1257 ee_sum[i].esum = fr->ener[i].e;
1258 ee_sum[i].eav = 0;
1260 ee_nsteps = 1;
1261 ee_nsum = 1;
1262 } else {
1263 if (ee_nsum > 0) {
1264 if (fr->step - start_step + 1 == ee_nsteps + fr->nsteps) {
1265 if (fr->nsum <= 1) {
1266 /* We have a sum of a single frame:
1267 * add the energy to the sums.
1269 for(i=0; i<fr->nre; i++) {
1270 ee_sum[i].eav +=
1271 dsqr(ee_sum[i].esum/ee_nsum - (ee_sum[i].esum + fr->ener[i].e)/(ee_nsum + 1))*
1272 ee_nsum*(ee_nsum + 1);
1273 ee_sum[i].esum += fr->ener[i].e;
1275 ee_nsum += 1;
1276 } else {
1277 /* Add the sums to the total */
1278 for(i=0; i<fr->nre; i++) {
1279 ee_sum[i].eav +=
1280 fr->ener[i].eav +
1281 dsqr(ee_sum[i].esum/ee_nsum - (ee_sum[i].esum + fr->ener[i].esum)/(ee_nsum + fr->nsum))*
1282 ee_nsum*(ee_nsum + fr->nsum)/(double)fr->nsum;
1283 ee_sum[i].esum += fr->ener[i].esum;
1285 ee_nsum += fr->nsum;
1287 } else {
1288 /* The interval does not match fr->nsteps:
1289 * can not do exact averages.
1291 ee_nsum = 0;
1293 ee_nsteps = fr->step - start_step + 1;
1298 * Define distance restraint legends. Can only be done after
1299 * the first frame has been read... (Then we know how many there are)
1301 if (bDisRe && bDRAll && !leg && (fr->ndisre > 0)) {
1302 t_iatom *fa;
1303 t_iparams *ip;
1305 fa = top->idef.il[F_DISRES].iatoms;
1306 ip = top->idef.iparams;
1308 if (fr->ndisre != top->idef.il[F_DISRES].nr/3)
1309 gmx_fatal(FARGS,"Number of disre pairs in the energy file (%d) does not match the number in the run input file (%d)\n",
1310 fr->ndisre,top->idef.il[F_DISRES].nr/3);
1312 snew(pairleg,fr->ndisre);
1313 for(i=0; i<fr->ndisre; i++) {
1314 snew(pairleg[i],30);
1315 j=fa[3*i+1];
1316 k=fa[3*i+2];
1317 gmx_mtop_atominfo_global(&mtop,j,&anm_j,&resnr_j,&resnm_j);
1318 gmx_mtop_atominfo_global(&mtop,k,&anm_k,&resnr_k,&resnm_k);
1319 sprintf(pairleg[i],"%d %s %d %s (%d)",
1320 resnr_j+1,anm_j,resnr_k+1,anm_k,
1321 ip[fa[3*i]].disres.label);
1323 set=select_it(fr->ndisre,pairleg,&nset);
1324 snew(leg,2*nset);
1325 for(i=0; (i<nset); i++) {
1326 snew(leg[2*i],32);
1327 sprintf(leg[2*i], "a %s",pairleg[set[i]]);
1328 snew(leg[2*i+1],32);
1329 sprintf(leg[2*i+1],"i %s",pairleg[set[i]]);
1331 xvgr_legend(fp_pairs,2*nset,leg,oenv);
1335 * Store energies for analysis afterwards...
1337 if (!bDisRe && (fr->nre > 0)) {
1338 if ((nenergy % 1000) == 0) {
1339 srenew(time,nenergy+1000);
1340 for(i=0; (i<=nset); i++) {
1341 srenew(eneset[i],nenergy+1000);
1342 if (bVisco)
1343 srenew(enesum[i],nenergy+1000);
1346 time[nenergy] = fr->t;
1347 sum=0;
1348 for(i=0; (i<nset); i++) {
1349 ener = fr->ener[set[i]].e;
1350 eneset[i][nenergy] = ener;
1351 sum += ener;
1352 if (bVisco) {
1353 enesum[i][nenergy] = fr->ener[set[i]].esum;
1355 /* Sum the actual frame energies,
1356 * for in case we do not have exact sums in the energy file.
1358 enersum.sum[i] += ener;
1359 enersum.sum2[i] += ener*ener;
1361 if (bSum) {
1362 eneset[nset][nenergy] = sum;
1364 nenergy++;
1365 enersum.nframes++;
1368 * Printing time, only when we do not want to skip frames
1370 if (!skip || teller % skip == 0) {
1371 if (bDisRe) {
1372 /*******************************************
1373 * D I S T A N C E R E S T R A I N T S
1374 *******************************************/
1375 if (fr->ndisre > 0) {
1376 print_time(out,fr->t);
1377 if (violaver == NULL)
1378 snew(violaver,fr->ndisre);
1380 /* Subtract bounds from distances, to calculate violations */
1381 calc_violations(fr->disre_rt,fr->disre_rm3tav,
1382 nbounds,pair,bounds,violaver,&sumt,&sumaver);
1384 fprintf(out," %8.4f %8.4f\n",sumaver,sumt);
1385 if (bDRAll) {
1386 print_time(fp_pairs,fr->t);
1387 for(i=0; (i<nset); i++) {
1388 sss=set[i];
1389 fprintf(fp_pairs," %8.4f",
1390 mypow(fr->disre_rm3tav[sss],minthird));
1391 fprintf(fp_pairs," %8.4f",
1392 fr->disre_rt[sss]);
1394 fprintf(fp_pairs,"\n");
1396 teller_disre++;
1399 /*******************************************
1400 * E N E R G I E S
1401 *******************************************/
1402 else {
1403 if (fr->nre > 0) {
1404 print_time(out,fr->t);
1405 if (bSum)
1406 print1(out,bDp,(eneset[nset][nenergy-1])/nmol-ezero);
1407 else if ((nset == 1) && bAll) {
1408 print1(out,bDp,fr->ener[set[0]].e);
1409 print1(out,bDp,fr->ener[set[0]].esum);
1410 print1(out,bDp,fr->ener[set[0]].eav);
1412 else for(i=0; (i<nset); i++)
1413 print1(out,bDp,(fr->ener[set[i]].e)/nmol-ezero);
1415 fprintf(out,"\n");
1417 if (bORIRE && fr->nblock>enx_i && fr->nr[enx_i]>0) {
1418 if (fr->nr[enx_i] != nor)
1419 gmx_fatal(FARGS,"Number of orientation restraints in energy file (%d) does not match with the topology (%d)",fr->nr[enx_i],nor);
1420 if (bORA || bODA)
1421 for(i=0; i<nor; i++)
1422 orient[i] += fr->block[enx_i][i];
1423 if (bODR)
1424 for(i=0; i<nor; i++)
1425 odrms[i] += sqr(fr->block[enx_i][i]-oobs[i]);
1426 if (bORT) {
1427 fprintf(fort," %10f",fr->t);
1428 for(i=0; i<norsel; i++)
1429 fprintf(fort," %g",fr->block[enx_i][orsel[i]]);
1430 fprintf(fort,"\n");
1432 if (bODT) {
1433 fprintf(fodt," %10f",fr->t);
1434 for(i=0; i<norsel; i++)
1435 fprintf(fodt," %g",fr->block[enx_i][orsel[i]]-oobs[orsel[i]]);
1436 fprintf(fodt,"\n");
1438 norfr++;
1440 if (bOTEN && fr->nblock>enxORT) {
1441 if (fr->nr[enxORT] != nex*12)
1442 gmx_fatal(FARGS,"Number of orientation experiments in energy file (%g) does not match with the topology (%d)",fr->nr[enxORT]/12,nex);
1443 fprintf(foten," %10f",fr->t);
1444 for(i=0; i<nex; i++)
1445 for(j=0; j<(bOvec?12:3); j++)
1446 fprintf(foten," %g",fr->block[enxORT][i*12+j]);
1447 fprintf(foten,"\n");
1452 } while (bCont && (timecheck == 0));
1454 fprintf(stderr,"\n");
1455 close_enx(fp);
1457 ffclose(out);
1459 if (bDRAll)
1460 ffclose(fp_pairs);
1462 if (bORT)
1463 ffclose(fort);
1464 if (bODT)
1465 ffclose(fodt);
1466 if (bORA) {
1467 out = xvgropen(opt2fn("-ora",NFILE,fnm),
1468 "Average calculated orientations",
1469 "Restraint label","",oenv);
1470 if (bOrinst)
1471 fprintf(out,"%s",orinst_sub);
1472 for(i=0; i<nor; i++)
1473 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr);
1474 ffclose(out);
1476 if (bODA) {
1477 out = xvgropen(opt2fn("-oda",NFILE,fnm),
1478 "Average restraint deviation",
1479 "Restraint label","",oenv);
1480 if (bOrinst)
1481 fprintf(out,"%s",orinst_sub);
1482 for(i=0; i<nor; i++)
1483 fprintf(out,"%5d %g\n",or_label[i],orient[i]/norfr-oobs[i]);
1484 ffclose(out);
1486 if (bODR) {
1487 out = xvgropen(opt2fn("-odr",NFILE,fnm),
1488 "RMS orientation restraint deviations",
1489 "Restraint label","",oenv);
1490 if (bOrinst)
1491 fprintf(out,"%s",orinst_sub);
1492 for(i=0; i<nor; i++)
1493 fprintf(out,"%5d %g\n",or_label[i],sqrt(odrms[i]/norfr));
1494 ffclose(out);
1496 if (bOTEN)
1497 ffclose(foten);
1499 if (bDisRe) {
1500 analyse_disre(opt2fn("-viol",NFILE,fnm),
1501 teller_disre,violaver,bounds,index,pair,nbounds,oenv);
1502 } else {
1503 analyse_ener(opt2bSet("-corr",NFILE,fnm),opt2fn("-corr",NFILE,fnm),
1504 bFee,bSum,bFluct,bVisco,opt2fn("-vis",NFILE,fnm),
1505 nmol,ndf,start_step,start_t,frame[cur].step,frame[cur].t,
1506 time,reftemp,ee_nsum,ee_sum,&enersum,
1507 nset,set,nenergy,eneset,enesum,leg,enm,Vaver,ezero,oenv);
1509 if (opt2bSet("-f2",NFILE,fnm)) {
1510 fec(opt2fn("-f2",NFILE,fnm), opt2fn("-ravg",NFILE,fnm),
1511 reftemp, nset, set, leg, nenergy, eneset, time ,oenv);
1515 const char *nxy = "-nxy";
1517 do_view(oenv,opt2fn("-o",NFILE,fnm),nxy);
1518 do_view(oenv,opt2fn_null("-ravg",NFILE,fnm),nxy);
1519 do_view(oenv,opt2fn_null("-ora",NFILE,fnm),nxy);
1520 do_view(oenv,opt2fn_null("-ort",NFILE,fnm),nxy);
1521 do_view(oenv,opt2fn_null("-oda",NFILE,fnm),nxy);
1522 do_view(oenv,opt2fn_null("-odr",NFILE,fnm),nxy);
1523 do_view(oenv,opt2fn_null("-odt",NFILE,fnm),nxy);
1524 do_view(oenv,opt2fn_null("-oten",NFILE,fnm),nxy);
1526 thanx(stderr);
1528 return 0;