Fixing copyright issues and code contributors
[alexxy/gromacs.git] / src / mdlib / ebin.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team,
6  * check out http://www.gromacs.org for more information.
7  * Copyright (c) 2012,2013, by the GROMACS development team, led by
8  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9  * others, as listed in the AUTHORS file in the top-level source
10  * directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 /* This file is completely threadsafe - keep it that way! */
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #include <math.h>
44 #include <string.h>
45 #include "sysstuff.h"
46 #include "smalloc.h"
47 #include "typedefs.h"
48 #include "gmx_fatal.h"
49 #include "string2.h"
50 #include "ebin.h"
51 #include "main.h"
52 #include "maths.h"
53 #include "vec.h"
54 #include "physics.h"
55
56 t_ebin *mk_ebin(void)
57 {
58   t_ebin *eb;
59   
60   snew(eb,1);
61   
62   return eb;
63 }
64
65 int get_ebin_space(t_ebin *eb,int nener,const char *enm[],const char *unit)
66 {
67     int  index;
68     int  i,f;
69     const char *u;
70
71     index = eb->nener;
72     eb->nener += nener;
73     srenew(eb->e,eb->nener);
74     srenew(eb->e_sim,eb->nener);
75     srenew(eb->enm,eb->nener);
76     for(i=index; (i<eb->nener); i++)
77     {
78         eb->e[i].e        = 0;
79         eb->e[i].eav      = 0;
80         eb->e[i].esum     = 0;
81         eb->e_sim[i].e    = 0;
82         eb->e_sim[i].eav  = 0;
83         eb->e_sim[i].esum = 0;
84         eb->enm[i].name = strdup(enm[i-index]);
85         if (unit != NULL)
86         {
87             eb->enm[i].unit = strdup(unit);
88         }
89         else
90         {
91             /* Determine the unit from the longname.
92              * These units should have been defined in ifunc.c
93              * But even better would be if all interactions functions
94              * return energies and all non-interaction function
95              * entries would be removed from the ifunc array.
96              */
97             u = unit_energy;
98             for(f=0; f<F_NRE; f++)
99             {
100                 if (strcmp(eb->enm[i].name,
101                            interaction_function[f].longname) == 0)
102                 {
103                     /* Only the terms in this list are not energies */
104                     switch (f) {
105                     case F_DISRESVIOL: u = unit_length;   break;
106                     case F_ORIRESDEV:  u = "obs";         break;
107                     case F_TEMP:       u = unit_temp_K;   break;
108                     case F_PDISPCORR:
109                     case F_PRES:       u = unit_pres_bar; break;
110                     }
111                 }
112             }
113             eb->enm[i].unit = strdup(u);
114         }
115     }
116     
117     return index;
118 }
119
120 void add_ebin(t_ebin *eb,int index,int nener,real ener[],gmx_bool bSum)
121 {
122     int      i,m;
123     double   e,sum,sigma,invmm,diff;
124     t_energy *eg,*egs;
125     
126     if ((index+nener > eb->nener) || (index < 0))
127     {
128         gmx_fatal(FARGS,"%s-%d: Energies out of range: index=%d nener=%d maxener=%d",
129                   __FILE__,__LINE__,index,nener,eb->nener);
130     }
131     
132     eg = &(eb->e[index]);
133     
134     for(i=0; (i<nener); i++)
135     {
136         eg[i].e      = ener[i];
137     }
138     
139     if (bSum)
140     {
141         egs = &(eb->e_sim[index]);
142         
143         m = eb->nsum;
144         
145         if (m == 0)
146         {
147             for(i=0; (i<nener); i++)
148             {
149                 eg[i].eav    = 0;
150                 eg[i].esum   = ener[i];
151                 egs[i].esum += ener[i];
152             }
153         }
154         else
155         {
156             invmm = (1.0/(double)m)/((double)m+1.0);
157             
158             for(i=0; (i<nener); i++)
159             {
160                 /* Value for this component */
161                 e = ener[i];
162                 
163                 /* first update sigma, then sum */
164                 diff         = eg[i].esum - m*e;
165                 eg[i].eav   += diff*diff*invmm;
166                 eg[i].esum  += e;
167                 egs[i].esum += e;
168             }
169         }
170     }
171 }
172
173 void ebin_increase_count(t_ebin *eb,gmx_bool bSum)
174 {
175     eb->nsteps++;
176     eb->nsteps_sim++;
177
178     if (bSum)
179     {
180         eb->nsum++;
181         eb->nsum_sim++;
182     }
183 }
184
185 void reset_ebin_sums(t_ebin *eb)
186 {
187     eb->nsteps = 0;
188     eb->nsum   = 0;
189     /* The actual sums are cleared when the next frame is stored */
190 }
191
192 void pr_ebin(FILE *fp,t_ebin *eb,int index,int nener,int nperline,
193              int prmode,gmx_bool bPrHead)
194 {
195     int  i,j,i0;
196     real ee=0;
197     int  rc;
198     char buf[30];
199
200     rc = 0;
201
202     if (index < 0)
203     {
204         gmx_fatal(FARGS,"Invalid index in pr_ebin: %d",index);
205     }
206     if (nener == -1)
207     {
208         nener = eb->nener;
209     }
210     else
211     {
212         nener = index + nener;
213     }
214     for(i=index; (i<nener) && rc>=0; ) 
215     {
216         if (bPrHead)
217         {
218             i0=i;
219             for(j=0; (j<nperline) && (i<nener) && rc>=0; j++,i++)
220             {
221                 if (strncmp(eb->enm[i].name,"Pres",4) == 0)
222                 {
223                     /* Print the pressure unit to avoid confusion */
224                     sprintf(buf,"%s (%s)",eb->enm[i].name,unit_pres_bar);
225                     rc = fprintf(fp,"%15s",buf);
226                 }
227                 else
228                 {
229                     rc = fprintf(fp,"%15s",eb->enm[i].name);
230                 }
231             }
232
233             if (rc >= 0)
234             {
235                 rc = fprintf(fp,"\n");
236             }
237
238             i=i0;
239         }
240         for(j=0; (j<nperline) && (i<nener) && rc>=0; j++,i++)
241         {
242             switch (prmode) {
243                 case eprNORMAL: ee = eb->e[i].e; break;
244                 case eprAVER:   ee = eb->e_sim[i].esum/eb->nsum_sim; break;
245                 default: gmx_fatal(FARGS,"Invalid print mode %d in pr_ebin",
246                                    prmode);
247             }
248
249             rc = fprintf(fp,"   %12.5e",ee);
250         }
251         if (rc >= 0)
252         {
253             rc = fprintf(fp,"\n");
254         }
255     }
256     if (rc < 0)
257     { 
258         gmx_fatal(FARGS,"Cannot write to logfile; maybe you are out of disk space?");
259     }
260 }
261
262 #ifdef DEBUGEBIN
263 int main(int argc,char *argv[])
264 {
265 #define NE 12
266 #define NT 7
267 #define NS 5
268
269   t_ebin *eb;
270   int    i;
271   char   buf[25];
272   char   *ce[NE],*ct[NT],*cs[NS];
273   real   e[NE],t[NT],s[NS];
274   int    ie,it,is;
275   
276   eb=mk_ebin();
277   for(i=0; (i<NE); i++) {
278     e[i]=i;
279     sprintf(buf,"e%d",i);
280     ce[i]=strdup(buf);
281   }
282   ie=get_ebin_space(eb,NE,ce);
283   add_ebin(eb,ie,NE,e,0);
284   for(i=0; (i<NS); i++) {
285     s[i]=i;
286     sprintf(buf,"s%d",i);
287     cs[i]=strdup(buf);
288   }
289   is=get_ebin_space(eb,NS,cs);
290   add_ebin(eb,is,NS,s,0);
291   for(i=0; (i<NT); i++) {
292     t[i]=i;
293     sprintf(buf,"t%d",i);
294     ct[i]=strdup(buf);
295   }
296   it=get_ebin_space(eb,NT,ct);
297   add_ebin(eb,it,NT,t,0);
298   
299   printf("Normal:\n");
300   pr_ebin(stdout,eb,0,-1,5,eprNORMAL,1);
301
302   printf("Average:\n");
303   pr_ebin(stdout,eb,ie,NE,5,eprAVER,1);
304   pr_ebin(stdout,eb,is,NS,3,eprAVER,1);
305   pr_ebin(stdout,eb,it,NT,4,eprAVER,1);
306 }
307 #endif