1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
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
34 * Green Red Orange Magenta Azure Cyan Skyblue
45 #include "gmx_fatal.h"
59 #include "mtop_util.h"
63 static real minthird
=-1.0/3.0,minsixth
=-1.0/6.0;
81 gmx_large_int_t nsteps
;
82 gmx_large_int_t npoints
;
90 static double mypow(double x
,double y
)
98 static int *select_it(int nre
,char *nm
[],int *nset
)
103 gmx_bool bVerbose
= TRUE
;
105 if ((getenv("VERBOSE")) != NULL
)
108 fprintf(stderr
,"Select the terms you want from the following list\n");
109 fprintf(stderr
,"End your selection with 0\n");
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");
121 if(1 != scanf("%d",&n
))
123 gmx_fatal(FARGS
,"Error reading user input");
125 if ((n
>0) && (n
<=nre
))
130 for(i
=(*nset
)=0; (i
<nre
); i
++)
139 static int strcount(const char *s1
,const char *s2
)
142 while (s1
&& s2
&& (toupper(s1
[n
]) == toupper(s2
[n
])))
147 static void chomp(char *buf
)
149 int len
= strlen(buf
);
151 while ((len
> 0) && (buf
[len
-1] == '\n')) {
157 static int *select_by_name(int nre
,gmx_enxnm_t
*nm
,int *nset
)
160 int n
,k
,kk
,j
,i
,nmatch
,nind
,nss
;
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";
168 if ((getenv("VERBOSE")) != NULL
)
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");
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
) {
188 fprintf(stderr
,"\n");
191 for(kk
=k
; kk
<k
+4; kk
++) {
192 if (kk
< nre
&& strlen(nm
[kk
].name
) > 14) {
200 fprintf(stderr
,fm4
,k
+1,newnm
[k
]);
206 fprintf(stderr
,fm2
,k
+1,newnm
[k
]);
215 fprintf(stderr
,"\n\n");
221 while (!bEOF
&& (fgets2(buf
,STRLEN
-1,stdin
))) {
222 /* Remove newlines */
228 /* Empty line means end of input */
229 bEOF
= (strlen(buf
) == 0);
234 /* First try to read an integer */
235 nss
= sscanf(ptr
,"%d",&nind
);
237 /* Zero means end of input */
240 } else if ((1<=nind
) && (nind
<=nre
)) {
243 fprintf(stderr
,"number %d is out of range\n",nind
);
247 /* Now try to read a string */
250 for(nind
=0; nind
<nre
; nind
++) {
251 if (gmx_strcasecmp(newnm
[nind
],ptr
) == 0) {
259 for(nind
=0; nind
<nre
; nind
++) {
260 if (gmx_strncasecmp(newnm
[nind
],ptr
,i
) == 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
) {
275 } while (!bEOF
&& (ptr
&& (strlen(ptr
) > 0)));
280 for(i
=(*nset
)=0; (i
<nre
); i
++)
287 gmx_fatal(FARGS
,"No energy terms selected");
289 for(i
=0; (i
<nre
); i
++)
296 static void get_orires_parms(const char *topnm
,
297 int *nor
,int *nex
,int **label
,real
**obs
)
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
;
317 gmx_fatal(FARGS
,"No orientation restraints in topology!\n");
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",
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
)
338 t_functype
*functype
;
340 int natoms
,i
,j
,k
,type
,ftype
,natom
;
348 read_tpx(topnm
,ir
,box
,&natoms
,NULL
,NULL
,NULL
,mtop
);
350 top
= gmx_mtop_generate_local_top(mtop
,ir
);
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
;
359 gmx_fatal(FARGS
,"No distance restraints in topology!\n");
361 /* Allocate memory */
366 /* Fill the bound array */
368 for(i
=0; (i
<top
->idef
.ntypes
); i
++) {
370 if (ftype
== F_DISRES
) {
372 label1
= ip
[i
].disres
.label
;
373 b
[nb
] = ip
[i
].disres
.up1
;
380 /* Fill the index array */
382 disres
= &(top
->idef
.il
[F_DISRES
]);
383 iatom
= disres
->iatoms
;
384 for(i
=j
=k
=0; (i
<disres
->nr
); ) {
386 ftype
= top
->idef
.functype
[type
];
387 natom
= interaction_function
[ftype
].nratoms
+1;
388 if (label1
!= top
->idef
.iparams
[type
].disres
.label
) {
390 label1
= top
->idef
.iparams
[type
].disres
.label
;
399 gmx_incons("get_bounds for distance restraints");
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;
412 double rsum
,rav
,sumaver
,sumt
;
416 for(i
=0; (i
<nb
); i
++) {
419 for(j
=index
[i
]; (j
<index
[i
+1]); j
++) {
421 viol
[j
] += mypow(rt
[j
],-3.0);
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
]);
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
)
441 double sum
,sumt
,sumaver
;
444 /* Subtract bounds from distances, to calculate violations */
445 calc_violations(violaver
,violaver
,
446 nbounds
,pair
,bounds
,NULL
,&sumt
,&sumaver
);
449 fprintf(stdout
,"\nSum of violations averaged over simulation: %g nm\n",
451 fprintf(stdout
,"Largest violation averaged over simulation: %g nm\n\n",
454 vout
=xvgropen(voutfn
,"r\\S-3\\N average violations","DR Index","nm",
458 for(i
=0; (i
<nbounds
); i
++) {
459 /* Do ensemble averaging */
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
]);
466 sum
= max(sum
,sumaver
);
467 fprintf(vout
,"%10d %10.5e\n",index
[i
],sumaver
);
470 for(j
=0; (j
<dr
.ndr
); j
++)
471 fprintf(vout
,"%10d %10.5e\n",j
,mypow(violaver
[j
]/nframes
,minthird
));
475 fprintf(stdout
,"\nSum of violations averaged over simulation: %g nm\n",
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
)
488 double av
[4],avold
[4];
495 dt
= (time
[1]-time
[0]);
498 for(i
=0; i
<=nsets
; i
++)
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
++)
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
]));
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
++) {
521 fprintf(fp0
," %10g",av
[m
]);
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
);
546 gmx_large_int_t nst_min
;
549 static void clear_ee_sum(ee_sum_t
*ees
)
557 static void add_ee_sum(ee_sum_t
*ees
,double sum
,int np
)
563 static void add_ee_av(ee_sum_t
*ees
)
567 av
= ees
->sum
/ees
->np
;
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
)
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
);
589 if (eee
->b
== 1 || eee
->nst
< eee
->nst_min
)
591 eee
->nst_min
= eee
->nst
;
596 static void calc_averages(int nset
,enerdata_t
*edat
,int nbmin
,int nbmax
)
599 double sum
,sum2
,sump
,see2
;
600 gmx_large_int_t steps
,np
,p
,bound_nb
;
604 double x
,sx
,sy
,sxx
,sxy
;
607 /* Check if we have exact statistics over all points */
608 for(i
=0; i
<nset
; 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.
618 for(f
=0; f
<edat
->nframes
&& !ed
->bExactStat
; f
++)
620 if (ed
->ener
[i
] != 0)
624 ed
->bExactStat
= (ed
->es
[f
].sum
!= 0);
628 ed
->bExactStat
= TRUE
;
634 for(i
=0; i
<nset
; i
++)
645 for(nb
=nbmin
; nb
<=nbmax
; nb
++)
648 clear_ee_sum(&eee
[nb
].sum
);
652 for(f
=0; f
<edat
->nframes
; f
++)
658 /* Add the sum and the sum of variances to the totals. */
664 sum2
+= dsqr(sum
/np
- (sum
+ es
->sum
)/(np
+ p
))
670 /* Add a single value to the sum and sum of squares. */
676 /* sum has to be increased after sum2 */
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);
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
)
706 eee
[nb
].nst
+= edat
->step
[f
] - edat
->step
[f
-1];
710 add_ee_sum(&eee
[nb
].sum
,es
->sum
,edat
->points
[f
]);
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
)
724 edat
->s
[i
].av
= sum
/np
;
727 edat
->s
[i
].rmsd
= sqrt(sum2
/np
);
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
);
740 edat
->s
[i
].slope
= 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.
752 char buf1
[STEPSTRSIZE
],buf2
[STEPSTRSIZE
];
753 fprintf(debug
,"Requested %d blocks, we have %d blocks, min %s nsteps %s\n",
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
);
766 edat
->s
[i
].ee
= sqrt(see2
/nee
);
776 static enerdata_t
*calc_sum(int nset
,enerdata_t
*edat
,int nbmin
,int nbmax
)
787 snew(s
->ener
,esum
->nframes
);
788 snew(s
->es
,esum
->nframes
);
790 s
->bExactStat
= TRUE
;
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
++)
804 for(i
=0; i
<nset
; i
++)
806 sum
+= edat
->s
[i
].ener
[f
];
810 for(i
=0; i
<nset
; i
++)
812 sum
+= edat
->s
[i
].es
[f
].sum
;
818 calc_averages(1,esum
,nbmin
,nbmax
);
823 static char *ee_pr(double ee
,char *buf
)
830 sprintf(buf
,"%s","--");
834 /* Round to two decimals by printing. */
835 sprintf(tmp
,"%.1e",ee
);
836 sscanf(tmp
,"%lf",&rnd
);
837 sprintf(buf
,"%g",rnd
);
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
,
847 gmx_large_int_t start_step
,double start_t
,
848 gmx_large_int_t step
,double t
,
849 double time
[], real reftemp
,
851 int nset
,int set
[],gmx_bool
*bIsEner
,
852 char **leg
,gmx_enxnm_t
*enm
,
853 real Vaver
,real ezero
,
855 const output_env_t oenv
)
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
;
867 real Temp
=-1,Pres
=-1,VarV
=-1,VarT
=-1,VarEtot
=-1,AvEtot
=0,VarEnthalpy
=-1;
870 char buf
[256],eebuf
[100];
872 nsteps
= step
- start_step
+ 1;
874 fprintf(stdout
,"Not enough steps (%s) for statistics\n",
875 gmx_step_str(nsteps
,buf
));
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
);
887 esum
= calc_sum(nset
,edat
,nbmin
,nbmax
);
890 if (edat
->npoints
== 0) {
896 for(i
=0; (i
<nset
); i
++) {
897 if (edat
->s
[i
].bExactStat
) {
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",
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");
928 fprintf(stdout
," %10s\n","-kT ln<e^(E/kT)>");
930 fprintf(stdout
,"\n");
931 fprintf(stdout
,"-------------------------------------------------------------------------------\n");
933 /* Initiate locals, only used with -sum */
936 beta
= 1.0/(BOLTZ
*reftemp
);
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
;
946 for(j
=0; (j
<edat
->nframes
); j
++) {
947 expE
+= exp(beta
*(edat
->s
[i
].ener
[j
] - aver
)/nmol
);
950 expEtot
+=expE
/edat
->nframes
;
952 fee
[i
] = log(expE
/edat
->nframes
)/beta
+ aver
/nmol
;
954 if (strstr(leg
[i
],"empera") != NULL
) {
957 } else if (strstr(leg
[i
],"olum") != NULL
) {
960 } else if (strstr(leg
[i
],"essure") != NULL
) {
962 } else if (strstr(leg
[i
],"otal") != NULL
) {
963 VarEtot
= sqr(stddev
);
965 } else if (strstr(leg
[i
],"nthalpy") != NULL
) {
966 VarEnthalpy
= sqr(stddev
);
969 pr_aver
= aver
/nmol
-ezero
;
970 pr_stddev
= stddev
/nmol
;
971 pr_errest
= errest
/nmol
;
979 /* Multiply the slope in steps with the number of steps taken */
980 totaldrift
= (edat
->nsteps
- 1)*edat
->s
[i
].slope
;
986 fprintf(stdout
,"%-24s %10g %10s %10g %10g",
987 leg
[i
],pr_aver
,ee_pr(pr_errest
,eebuf
),pr_stddev
,totaldrift
);
989 fprintf(stdout
," %10g",fee
[i
]);
991 fprintf(stdout
," (%s)\n",enm
[set
[i
]].unit
);
994 for(j
=0; (j
<edat
->nframes
); j
++)
995 edat
->s
[i
].ener
[j
] -= aver
;
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 */
1005 fprintf(stdout
," %10g %10g\n",
1006 log(expEtot
)/beta
+ esum
->s
[0].av
/nmol
,log(expEtot
)/beta
);
1008 fprintf(stdout
,"\n");
1010 if (bTempFluct
&& Temp
!= -1) {
1011 printf("\nTemperature dependent fluctuation properties at T = %g. #constr/mol = %d\n",Temp
,nconstr
);
1013 printf("Warning: nmol = %d, this may not be what you want.\n",
1016 real tmp
= VarV
/(Vaver
*BOLTZ
*Temp
*PRESFAC
);
1018 printf("Isothermal Compressibility: %10g /%s\n",
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
) -
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
) -
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);
1049 const char* leg
[] = { "Shear", "Bulk" };
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!
1060 for(i
=0; i
<12; i
++) {
1061 snew(eneset
[i
],edat
->nframes
);
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 */
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
);
1116 strcpy(buf
,"Autocorrelation of Energy Fluctuations");
1118 strcpy(buf
,"Energy Autocorrelation");
1120 do_autocorr(corrfn
,oenv
,buf
,edat
->nframes
,
1122 bSum
? &edat
->s
[nset
-1].ener
: eneset
,
1123 (delta_t
/edat
->nframes
),eacNormal
,FALSE
);
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
)
1137 fprintf(fp
," %16.12f",e
);
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" };
1151 int nre
,timecheck
,step
,nenergy
,nenergy2
,maxenergy
;
1157 gmx_enxnm_t
*enm
=NULL
;
1161 /* read second energy file */
1164 enx
= open_enx(ene2fn
,"r");
1165 do_enxnms(enx
,&(fr
->nre
),&enm
);
1167 snew(eneset2
,nset
+1);
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
1176 bCont
= do_enx(enx
,fr
);
1179 timecheck
= check_times(fr
->t
);
1181 } while (bCont
&& (timecheck
< 0));
1183 /* Store energies for analysis afterwards... */
1184 if ((timecheck
== 0) && bCont
) {
1186 if ( nenergy2
>= maxenergy
) {
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
;
1199 } while (bCont
&& (timecheck
== 0));
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 */
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");
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
);
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
);
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
];
1245 gmx_bool first
=FALSE
;
1246 int nblock_hist
=0, nblock_dh
=0, nblock_dhcoll
=0;
1249 double temp
=0, start_time
=0, delta_time
=0, start_lambda
=0, delta_lambda
=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
)
1259 else if (fr
->block
[i
].id
== enxDH
)
1263 else if (fr
->block
[i
].id
== enxDHCOLL
)
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 */
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.");
1295 sprintf(title
,"%s, %s",dhdl
,deltag
);
1296 sprintf(label_x
,"%s (%s)","Time",unit_time
);
1297 sprintf(label_y
,"(%s)",unit_energy
);
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
,
1307 sprintf(buf
,"T = %g (K), %s = %g", temp
, lambda
, start_lambda
);
1308 xvgr_subtitle(*fp_dhdl
,buf
,oenv
);
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;
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
;
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
++)
1349 x0
=blk
->sub
[1].lval
[2+j
];
1354 "N(%s(%s=%g) | %s=%g)",
1355 deltag
, lambda
, foreign_lambda
,
1356 lambda
, start_lambda
);
1360 sprintf(legend
, "N(%s | %s=%g)",
1361 dhdl
, lambda
, start_lambda
);
1365 xvgr_new_dataset(*fp_dhdl
, setnr
, 1, lg
, oenv
);
1367 for(k
=0;k
<blk
->sub
[j
+2].nr
;k
++)
1372 hist
=blk
->sub
[j
+2].ival
[k
];
1375 fprintf(*fp_dhdl
,"%g %d\n%g %d\n", xmin
, 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 */
1388 (*samples
) += (int)(sum
/nblock_hist
);
1394 char **setnames
=NULL
;
1395 int nnames
=nblock_dh
;
1397 if (fabs(delta_lambda
) > 1e-9)
1403 snew(setnames
, nnames
);
1407 if (fabs(delta_lambda
) > 1e-9)
1409 /* lambda is a plotted value */
1410 setnames
[j
]=gmx_strdup(lambda
);
1415 for(i
=0;i
<fr
->nblock
;i
++)
1417 t_enxblock
*blk
=&(fr
->block
[i
]);
1418 if (blk
->id
== enxDH
)
1422 /* do the legends */
1424 double foreign_lambda
;
1426 derivative
=blk
->sub
[0].ival
[0];
1427 foreign_lambda
=blk
->sub
[1].dval
[0];
1431 sprintf(buf
, "%s %s %g",dhdl
,lambda
,start_lambda
);
1435 sprintf(buf
, "%s %s %g",deltag
,lambda
,
1438 setnames
[j
] = gmx_strdup(buf
);
1448 if (len
!=blk
->sub
[2].nr
)
1451 "Length inconsistency in dhdl data");
1460 xvgr_legend(*fp_dhdl
, nblock_dh
, (const char**)setnames
, oenv
);
1462 for(i
=0;i
<nblock_dh
;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
)
1486 if (blk
->sub
[2].type
== xdr_datatype_float
)
1488 value
=blk
->sub
[2].fval
[i
];
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",
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;
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
[] = {
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
;
1647 gmx_localtop_t
*top
=NULL
;
1651 gmx_enxnm_t
*enm
=NULL
;
1652 t_enxframe
*frame
,*fr
=NULL
;
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;
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
;
1667 int *set
=NULL
,i
,j
,k
,nset
,sss
;
1668 gmx_bool
*bIsEner
=NULL
;
1669 char **pairleg
,**odtleg
,**otenleg
;
1672 char *anm_j
,*anm_k
,*resnm_j
,*resnm_k
;
1673 int resnr_j
,resnr_k
;
1674 const char *orinst_sub
= "@ subtitle \"instantaneous\"\n";
1677 t_enxblock
*blk
=NULL
;
1678 t_enxblock
*blk_disre
=NULL
;
1680 int dh_blocks
=0, dh_hists
=0, dh_samples
=0, dh_lambdas
=0;
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)
1704 CopyRight(stderr
,argv
[0]);
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
);
1725 fp
= open_enx(ftp2fn(efEDR
,NFILE
,fnm
),"r");
1726 do_enxnms(fp
,&nre
,&enm
);
1730 bVisco
= opt2bSet("-vis",NFILE
,fnm
);
1732 if (!bDisRe
&& !bDHDL
)
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
])) {
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");
1754 gmx_fatal(FARGS
,"Could not find term %s for viscosity calculation",
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) {
1773 strcat(buf
,enm
[set
[i
]].unit
);
1777 out
=xvgropen(opt2fn("-o",NFILE
,fnm
),"Gromacs Energies","Time (ps)",buf
,
1781 for(i
=0; (i
<nset
); i
++)
1782 leg
[i
] = enm
[set
[i
]].name
;
1784 leg
[nset
]=strdup("Sum");
1785 xvgr_legend(out
,nset
+1,(const char**)leg
,oenv
);
1788 xvgr_legend(out
,nset
,(const char**)leg
,oenv
);
1791 for(i
=0; (i
<nset
); i
++) {
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");
1804 if (bORIRE
|| bOTEN
)
1805 get_orires_parms(ftp2fn(efTPX
,NFILE
,fnm
),&nor
,&nex
,&or_label
,&oobs
);
1818 fprintf(stderr
,"Select the orientation restraint labels you want (-1 is all)\n");
1819 fprintf(stderr
,"End your selection with 0\n");
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
);
1834 for(i
=0; i
<nor
; i
++)
1837 /* Build the selection */
1839 for(i
=0; i
<j
; i
++) {
1840 for(k
=0; k
<nor
; k
++)
1841 if (or_label
[k
] == orsel
[i
]) {
1847 fprintf(stderr
,"Orientation restraint label %d not found\n",
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
]]);
1857 fort
=xvgropen(opt2fn("-ort",NFILE
,fnm
), "Calculated orientations",
1858 "Time (ps)","",oenv
);
1860 fprintf(fort
,"%s",orinst_sub
);
1861 xvgr_legend(fort
,norsel
,(const char**)odtleg
,oenv
);
1864 fodt
=xvgropen(opt2fn("-odt",NFILE
,fnm
),
1865 "Orientation restraint deviation",
1866 "Time (ps)","",oenv
);
1868 fprintf(fodt
,"%s",orinst_sub
);
1869 xvgr_legend(fodt
,norsel
,(const char**)odtleg
,oenv
);
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
);
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
);
1894 nbounds
=get_bounds(ftp2fn(efTPX
,NFILE
,fnm
),&bounds
,&index
,&pair
,&npairs
,
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
);
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",
1910 /* Initiate energies and set them to zero */
1919 /* Initiate counters */
1922 bFoundStart
= FALSE
;
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
1930 bCont
= do_enx(fp
,&(frame
[NEXT
]));
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
]);
1942 /* The frame contains energies, so update cur */
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);
1958 edat
.step
[nfr
] = fr
->step
;
1963 /* Initiate the previous step data */
1964 start_step
= fr
->step
;
1966 /* Initiate the energy sums */
1967 edat
.steps
[nfr
] = 1;
1968 edat
.points
[nfr
] = 1;
1969 for(i
=0; i
<nset
; i
++)
1972 edat
.s
[i
].es
[nfr
].sum
= fr
->ener
[sss
].e
;
1973 edat
.s
[i
].es
[nfr
].sum2
= 0;
1980 edat
.steps
[nfr
] = fr
->nsteps
;
1982 if (fr
->step
- start_step
+ 1 == edat
.nsteps
+ fr
->nsteps
)
1986 edat
.points
[nfr
] = 1;
1987 for(i
=0; i
<nset
; i
++)
1990 edat
.s
[i
].es
[nfr
].sum
= fr
->ener
[sss
].e
;
1991 edat
.s
[i
].es
[nfr
].sum2
= 0;
1997 edat
.points
[nfr
] = fr
->nsum
;
1998 for(i
=0; i
<nset
; 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
;
2009 /* The interval does not match fr->nsteps:
2010 * can not do exact averages.
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
)
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);
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
);
2060 for(i
=0; (i
<nset
); i
++)
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
;
2081 * Printing time, only when we do not want to skip frames
2083 if (!skip
|| teller
% skip
== 0) {
2085 /*******************************************
2086 * D I S T A N C E R E S T R A I N T S
2087 *******************************************/
2091 float *disre_rt
= blk_disre
->sub
[0].fval
;
2092 float *disre_rm3tav
= blk_disre
->sub
[1].fval
;
2094 double *disre_rt
= blk_disre
->sub
[0].dval
;
2095 double *disre_rm3tav
= blk_disre
->sub
[1].dval
;
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
);
2108 print_time(fp_pairs
,fr
->t
);
2109 for(i
=0; (i
<nset
); 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");
2121 do_dhdl(fr
, &fp_dhdl
, opt2fn("-odh",NFILE
,fnm
),
2122 &dh_blocks
, &dh_hists
, &dh_samples
, &dh_lambdas
,
2125 /*******************************************
2127 *******************************************/
2132 /* We skip frames with single points (usually only the first frame),
2133 * since they would result in an average plot with outliers.
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
));
2145 print_time(out
,fr
->t
);
2149 for(i
=0; i
<nset
; i
++)
2151 sum
+= fr
->ener
[set
[i
]].e
;
2153 print1(out
,bDp
,sum
/nmol
-ezero
);
2157 for(i
=0; (i
<nset
); i
++)
2161 print1(out
,bDp
,(fr
->ener
[set
[i
]].e
)/nmol
-ezero
);
2165 print1(out
,bDp
,fr
->ener
[set
[i
]].e
);
2173 /* we first count the blocks that have id 0: the orire blocks */
2175 for(b
=0;b
<fr
->nblock
;b
++)
2177 if (fr
->block
[b
].id
== mde_block_type_orire
)
2181 blk
= find_block_id_enxframe(fr
, enx_i
, NULL
);
2185 xdr_datatype dt
=xdr_datatype_float
;
2187 xdr_datatype dt
=xdr_datatype_double
;
2191 if ( (blk
->nsub
!= 1) || (blk
->sub
[0].type
!=dt
) )
2193 gmx_fatal(FARGS
,"Orientational restraints read in incorrectly");
2196 vals
=blk
->sub
[0].fval
;
2198 vals
=blk
->sub
[0].dval
;
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
);
2205 for(i
=0; i
<nor
; i
++)
2206 orient
[i
] += vals
[i
];
2210 for(i
=0; i
<nor
; i
++)
2211 odrms
[i
] += sqr(vals
[i
]-oobs
[i
]);
2215 fprintf(fort
," %10f",fr
->t
);
2216 for(i
=0; i
<norsel
; i
++)
2217 fprintf(fort
," %g",vals
[orsel
[i
]]);
2222 fprintf(fodt
," %10f",fr
->t
);
2223 for(i
=0; i
<norsel
; i
++)
2224 fprintf(fodt
," %g", vals
[orsel
[i
]]-oobs
[orsel
[i
]]);
2229 blk
= find_block_id_enxframe(fr
, enxORT
, NULL
);
2233 xdr_datatype dt
=xdr_datatype_float
;
2235 xdr_datatype dt
=xdr_datatype_double
;
2239 if ( (blk
->nsub
!= 1) || (blk
->sub
[0].type
!=dt
) )
2240 gmx_fatal(FARGS
,"Orientational restraints read in incorrectly");
2242 vals
=blk
->sub
[0].fval
;
2244 vals
=blk
->sub
[0].dval
;
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");
2275 out
= xvgropen(opt2fn("-ora",NFILE
,fnm
),
2276 "Average calculated orientations",
2277 "Restraint label","",oenv
);
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
);
2285 out
= xvgropen(opt2fn("-oda",NFILE
,fnm
),
2286 "Average restraint deviation",
2287 "Restraint label","",oenv
);
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
]);
2295 out
= xvgropen(opt2fn("-odr",NFILE
,fnm
),
2296 "RMS orientation restraint deviations",
2297 "Restraint label","",oenv
);
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
));
2309 analyse_disre(opt2fn("-viol",NFILE
,fnm
),
2310 teller_disre
,violaver
,bounds
,index
,pair
,nbounds
,oenv
);
2317 printf("\n\nWrote %d lambda values with %d samples as ",
2318 dh_lambdas
, dh_samples
);
2321 printf("%d dH histograms ", dh_hists
);
2325 printf("%d dH data blocks ", dh_blocks
);
2327 printf("to %s\n", opt2fn("-odh",NFILE
,fnm
));
2332 gmx_fatal(FARGS
, "No dH data in %s\n", opt2fn("-f",NFILE
,fnm
));
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
,
2343 nset
,set
,bIsEner
,leg
,enm
,Vaver
,ezero
,nbmin
,nbmax
,
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
);