Encapsulate gmx_wallclock_accounting_t into new timing module
[alexxy/gromacs.git] / src / gromacs / mdlib / tpi.c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
3  *
4  *                This source code is part of
5  *
6  *                 G   R   O   M   A   C   S
7  *
8  *          GROningen MAchine for Chemical Simulations
9  *
10  *                        VERSION 3.2.0
11  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13  * Copyright (c) 2001-2004, The GROMACS development team,
14  * check out http://www.gromacs.org for more information.
15
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.
20  *
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.
27  *
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.
30  *
31  * For more info, check our website at http://www.gromacs.org
32  *
33  * And Hey:
34  * GROwing Monsters And Cloning Shrimps
35  */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <string.h>
41 #include <time.h>
42 #include <math.h>
43 #include "sysstuff.h"
44 #include "string2.h"
45 #include "network.h"
46 #include "confio.h"
47 #include "smalloc.h"
48 #include "nrnb.h"
49 #include "main.h"
50 #include "chargegroup.h"
51 #include "force.h"
52 #include "macros.h"
53 #include "random.h"
54 #include "names.h"
55 #include "gmx_fatal.h"
56 #include "txtdump.h"
57 #include "typedefs.h"
58 #include "update.h"
59 #include "random.h"
60 #include "constr.h"
61 #include "vec.h"
62 #include "statutil.h"
63 #include "tgroup.h"
64 #include "mdebin.h"
65 #include "vsite.h"
66 #include "force.h"
67 #include "mdrun.h"
68 #include "domdec.h"
69 #include "partdec.h"
70 #include "gmx_random.h"
71 #include "physics.h"
72 #include "xvgr.h"
73 #include "mdatoms.h"
74 #include "ns.h"
75 #include "gmx_wallcycle.h"
76 #include "mtop_util.h"
77 #include "gmxfio.h"
78 #include "pme.h"
79 #include "gbutil.h"
80 #include "gromacs/timing/walltime_accounting.h"
81
82 #ifdef GMX_X86_SSE2
83 #include "gmx_x86_sse2.h"
84 #endif
85
86
87 static void global_max(t_commrec *cr, int *n)
88 {
89     int *sum, i;
90
91     snew(sum, cr->nnodes);
92     sum[cr->nodeid] = *n;
93     gmx_sumi(cr->nnodes, sum, cr);
94     for (i = 0; i < cr->nnodes; i++)
95     {
96         *n = max(*n, sum[i]);
97     }
98
99     sfree(sum);
100 }
101
102 static void realloc_bins(double **bin, int *nbin, int nbin_new)
103 {
104     int i;
105
106     if (nbin_new != *nbin)
107     {
108         srenew(*bin, nbin_new);
109         for (i = *nbin; i < nbin_new; i++)
110         {
111             (*bin)[i] = 0;
112         }
113         *nbin = nbin_new;
114     }
115 }
116
117 double do_tpi(FILE *fplog, t_commrec *cr,
118               int nfile, const t_filenm fnm[],
119               const output_env_t oenv, gmx_bool bVerbose, gmx_bool gmx_unused bCompact,
120               int gmx_unused nstglobalcomm,
121               gmx_vsite_t gmx_unused *vsite, gmx_constr_t gmx_unused constr,
122               int gmx_unused stepout,
123               t_inputrec *inputrec,
124               gmx_mtop_t *top_global, t_fcdata *fcd,
125               t_state *state,
126               t_mdatoms *mdatoms,
127               t_nrnb *nrnb, gmx_wallcycle_t wcycle,
128               gmx_edsam_t gmx_unused ed,
129               t_forcerec *fr,
130               int gmx_unused repl_ex_nst, int gmx_unused repl_ex_nex, int gmx_unused repl_ex_seed,
131               gmx_membed_t gmx_unused membed,
132               real gmx_unused cpt_period, real gmx_unused max_hours,
133               const char gmx_unused *deviceOptions,
134               unsigned long gmx_unused Flags,
135               gmx_walltime_accounting_t walltime_accounting)
136 {
137     const char     *TPI = "Test Particle Insertion";
138     gmx_localtop_t *top;
139     gmx_groups_t   *groups;
140     gmx_enerdata_t *enerd;
141     rvec           *f;
142     real            lambda, t, temp, beta, drmax, epot;
143     double          embU, sum_embU, *sum_UgembU, V, V_all, VembU_all;
144     t_trxstatus    *status;
145     t_trxframe      rerun_fr;
146     gmx_bool        bDispCorr, bCharge, bRFExcl, bNotLastFrame, bStateChanged, bNS, bOurStep;
147     tensor          force_vir, shake_vir, vir, pres;
148     int             cg_tp, a_tp0, a_tp1, ngid, gid_tp, nener, e;
149     rvec           *x_mol;
150     rvec            mu_tot, x_init, dx, x_tp;
151     int             nnodes, frame, nsteps, step;
152     int             i, start, end;
153     gmx_rng_t       tpi_rand;
154     FILE           *fp_tpi = NULL;
155     char           *ptr, *dump_pdb, **leg, str[STRLEN], str2[STRLEN];
156     double          dbl, dump_ener;
157     gmx_bool        bCavity;
158     int             nat_cavity  = 0, d;
159     real           *mass_cavity = NULL, mass_tot;
160     int             nbin;
161     double          invbinw, *bin, refvolshift, logV, bUlogV;
162     real            dvdl, prescorr, enercorr, dvdlcorr;
163     gmx_bool        bEnergyOutOfBounds;
164     const char     *tpid_leg[2] = {"direct", "reweighted"};
165
166     /* Since there is no upper limit to the insertion energies,
167      * we need to set an upper limit for the distribution output.
168      */
169     real bU_bin_limit      = 50;
170     real bU_logV_bin_limit = bU_bin_limit + 10;
171
172     nnodes = cr->nnodes;
173
174     top = gmx_mtop_generate_local_top(top_global, inputrec);
175
176     groups = &top_global->groups;
177
178     bCavity = (inputrec->eI == eiTPIC);
179     if (bCavity)
180     {
181         ptr = getenv("GMX_TPIC_MASSES");
182         if (ptr == NULL)
183         {
184             nat_cavity = 1;
185         }
186         else
187         {
188             /* Read (multiple) masses from env var GMX_TPIC_MASSES,
189              * The center of mass of the last atoms is then used for TPIC.
190              */
191             nat_cavity = 0;
192             while (sscanf(ptr, "%lf%n", &dbl, &i) > 0)
193             {
194                 srenew(mass_cavity, nat_cavity+1);
195                 mass_cavity[nat_cavity] = dbl;
196                 fprintf(fplog, "mass[%d] = %f\n",
197                         nat_cavity+1, mass_cavity[nat_cavity]);
198                 nat_cavity++;
199                 ptr += i;
200             }
201             if (nat_cavity == 0)
202             {
203                 gmx_fatal(FARGS, "Found %d masses in GMX_TPIC_MASSES", nat_cavity);
204             }
205         }
206     }
207
208     /*
209        init_em(fplog,TPI,inputrec,&lambda,nrnb,mu_tot,
210        state->box,fr,mdatoms,top,cr,nfile,fnm,NULL,NULL);*/
211     /* We never need full pbc for TPI */
212     fr->ePBC = epbcXYZ;
213     /* Determine the temperature for the Boltzmann weighting */
214     temp = inputrec->opts.ref_t[0];
215     if (fplog)
216     {
217         for (i = 1; (i < inputrec->opts.ngtc); i++)
218         {
219             if (inputrec->opts.ref_t[i] != temp)
220             {
221                 fprintf(fplog, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
222                 fprintf(stderr, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
223             }
224         }
225         fprintf(fplog,
226                 "\n  The temperature for test particle insertion is %.3f K\n\n",
227                 temp);
228     }
229     beta = 1.0/(BOLTZ*temp);
230
231     /* Number of insertions per frame */
232     nsteps = inputrec->nsteps;
233
234     /* Use the same neighborlist with more insertions points
235      * in a sphere of radius drmax around the initial point
236      */
237     /* This should be a proper mdp parameter */
238     drmax = inputrec->rtpi;
239
240     /* An environment variable can be set to dump all configurations
241      * to pdb with an insertion energy <= this value.
242      */
243     dump_pdb  = getenv("GMX_TPI_DUMP");
244     dump_ener = 0;
245     if (dump_pdb)
246     {
247         sscanf(dump_pdb, "%lf", &dump_ener);
248     }
249
250     atoms2md(top_global, inputrec, 0, NULL, 0, top_global->natoms, mdatoms);
251     update_mdatoms(mdatoms, inputrec->fepvals->init_lambda);
252
253     snew(enerd, 1);
254     init_enerdata(groups->grps[egcENER].nr, inputrec->fepvals->n_lambda, enerd);
255     snew(f, top_global->natoms);
256
257     /* Print to log file  */
258     walltime_accounting_start(walltime_accounting);
259     print_date_and_time(fplog, cr->nodeid,
260                         "Started Test Particle Insertion",
261                         walltime_accounting);
262     wallcycle_start(wcycle, ewcRUN);
263
264     /* The last charge group is the group to be inserted */
265     cg_tp = top->cgs.nr - 1;
266     a_tp0 = top->cgs.index[cg_tp];
267     a_tp1 = top->cgs.index[cg_tp+1];
268     if (debug)
269     {
270         fprintf(debug, "TPI cg %d, atoms %d-%d\n", cg_tp, a_tp0, a_tp1);
271     }
272     if (a_tp1 - a_tp0 > 1 &&
273         (inputrec->rlist < inputrec->rcoulomb ||
274          inputrec->rlist < inputrec->rvdw))
275     {
276         gmx_fatal(FARGS, "Can not do TPI for multi-atom molecule with a twin-range cut-off");
277     }
278     snew(x_mol, a_tp1-a_tp0);
279
280     bDispCorr = (inputrec->eDispCorr != edispcNO);
281     bCharge   = FALSE;
282     for (i = a_tp0; i < a_tp1; i++)
283     {
284         /* Copy the coordinates of the molecule to be insterted */
285         copy_rvec(state->x[i], x_mol[i-a_tp0]);
286         /* Check if we need to print electrostatic energies */
287         bCharge |= (mdatoms->chargeA[i] != 0 ||
288                     (mdatoms->chargeB && mdatoms->chargeB[i] != 0));
289     }
290     bRFExcl = (bCharge && EEL_RF(fr->eeltype) && fr->eeltype != eelRF_NEC);
291
292     calc_cgcm(fplog, cg_tp, cg_tp+1, &(top->cgs), state->x, fr->cg_cm);
293     if (bCavity)
294     {
295         if (norm(fr->cg_cm[cg_tp]) > 0.5*inputrec->rlist && fplog)
296         {
297             fprintf(fplog, "WARNING: Your TPI molecule is not centered at 0,0,0\n");
298             fprintf(stderr, "WARNING: Your TPI molecule is not centered at 0,0,0\n");
299         }
300     }
301     else
302     {
303         /* Center the molecule to be inserted at zero */
304         for (i = 0; i < a_tp1-a_tp0; i++)
305         {
306             rvec_dec(x_mol[i], fr->cg_cm[cg_tp]);
307         }
308     }
309
310     if (fplog)
311     {
312         fprintf(fplog, "\nWill insert %d atoms %s partial charges\n",
313                 a_tp1-a_tp0, bCharge ? "with" : "without");
314
315         fprintf(fplog, "\nWill insert %d times in each frame of %s\n",
316                 nsteps, opt2fn("-rerun", nfile, fnm));
317     }
318
319     if (!bCavity)
320     {
321         if (inputrec->nstlist > 1)
322         {
323             if (drmax == 0 && a_tp1-a_tp0 == 1)
324             {
325                 gmx_fatal(FARGS, "Re-using the neighborlist %d times for insertions of a single atom in a sphere of radius %f does not make sense", inputrec->nstlist, drmax);
326             }
327             if (fplog)
328             {
329                 fprintf(fplog, "Will use the same neighborlist for %d insertions in a sphere of radius %f\n", inputrec->nstlist, drmax);
330             }
331         }
332     }
333     else
334     {
335         if (fplog)
336         {
337             fprintf(fplog, "Will insert randomly in a sphere of radius %f around the center of the cavity\n", drmax);
338         }
339     }
340
341     ngid   = groups->grps[egcENER].nr;
342     gid_tp = GET_CGINFO_GID(fr->cginfo[cg_tp]);
343     nener  = 1 + ngid;
344     if (bDispCorr)
345     {
346         nener += 1;
347     }
348     if (bCharge)
349     {
350         nener += ngid;
351         if (bRFExcl)
352         {
353             nener += 1;
354         }
355         if (EEL_FULL(fr->eeltype))
356         {
357             nener += 1;
358         }
359     }
360     snew(sum_UgembU, nener);
361
362     /* Initialize random generator */
363     tpi_rand = gmx_rng_init(inputrec->ld_seed);
364
365     if (MASTER(cr))
366     {
367         fp_tpi = xvgropen(opt2fn("-tpi", nfile, fnm),
368                           "TPI energies", "Time (ps)",
369                           "(kJ mol\\S-1\\N) / (nm\\S3\\N)", oenv);
370         xvgr_subtitle(fp_tpi, "f. are averages over one frame", oenv);
371         snew(leg, 4+nener);
372         e = 0;
373         sprintf(str, "-kT log(<Ve\\S-\\betaU\\N>/<V>)");
374         leg[e++] = strdup(str);
375         sprintf(str, "f. -kT log<e\\S-\\betaU\\N>");
376         leg[e++] = strdup(str);
377         sprintf(str, "f. <e\\S-\\betaU\\N>");
378         leg[e++] = strdup(str);
379         sprintf(str, "f. V");
380         leg[e++] = strdup(str);
381         sprintf(str, "f. <Ue\\S-\\betaU\\N>");
382         leg[e++] = strdup(str);
383         for (i = 0; i < ngid; i++)
384         {
385             sprintf(str, "f. <U\\sVdW %s\\Ne\\S-\\betaU\\N>",
386                     *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
387             leg[e++] = strdup(str);
388         }
389         if (bDispCorr)
390         {
391             sprintf(str, "f. <U\\sdisp c\\Ne\\S-\\betaU\\N>");
392             leg[e++] = strdup(str);
393         }
394         if (bCharge)
395         {
396             for (i = 0; i < ngid; i++)
397             {
398                 sprintf(str, "f. <U\\sCoul %s\\Ne\\S-\\betaU\\N>",
399                         *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
400                 leg[e++] = strdup(str);
401             }
402             if (bRFExcl)
403             {
404                 sprintf(str, "f. <U\\sRF excl\\Ne\\S-\\betaU\\N>");
405                 leg[e++] = strdup(str);
406             }
407             if (EEL_FULL(fr->eeltype))
408             {
409                 sprintf(str, "f. <U\\sCoul recip\\Ne\\S-\\betaU\\N>");
410                 leg[e++] = strdup(str);
411             }
412         }
413         xvgr_legend(fp_tpi, 4+nener, (const char**)leg, oenv);
414         for (i = 0; i < 4+nener; i++)
415         {
416             sfree(leg[i]);
417         }
418         sfree(leg);
419     }
420     clear_rvec(x_init);
421     V_all     = 0;
422     VembU_all = 0;
423
424     invbinw = 10;
425     nbin    = 10;
426     snew(bin, nbin);
427
428     bNotLastFrame = read_first_frame(oenv, &status, opt2fn("-rerun", nfile, fnm),
429                                      &rerun_fr, TRX_NEED_X);
430     frame = 0;
431
432     if (rerun_fr.natoms - (bCavity ? nat_cavity : 0) !=
433         mdatoms->nr - (a_tp1 - a_tp0))
434     {
435         gmx_fatal(FARGS, "Number of atoms in trajectory (%d)%s "
436                   "is not equal the number in the run input file (%d) "
437                   "minus the number of atoms to insert (%d)\n",
438                   rerun_fr.natoms, bCavity ? " minus one" : "",
439                   mdatoms->nr, a_tp1-a_tp0);
440     }
441
442     refvolshift = log(det(rerun_fr.box));
443
444 #ifdef GMX_X86_SSE2
445     /* Make sure we don't detect SSE overflow generated before this point */
446     gmx_mm_check_and_reset_overflow();
447 #endif
448
449     while (bNotLastFrame)
450     {
451         lambda = rerun_fr.lambda;
452         t      = rerun_fr.time;
453
454         sum_embU = 0;
455         for (e = 0; e < nener; e++)
456         {
457             sum_UgembU[e] = 0;
458         }
459
460         /* Copy the coordinates from the input trajectory */
461         for (i = 0; i < rerun_fr.natoms; i++)
462         {
463             copy_rvec(rerun_fr.x[i], state->x[i]);
464         }
465         copy_mat(rerun_fr.box, state->box);
466
467         V    = det(state->box);
468         logV = log(V);
469
470         bStateChanged = TRUE;
471         bNS           = TRUE;
472         for (step = 0; step < nsteps; step++)
473         {
474             /* In parallel all nodes generate all random configurations.
475              * In that way the result is identical to a single cpu tpi run.
476              */
477             if (!bCavity)
478             {
479                 /* Random insertion in the whole volume */
480                 bNS = (step % inputrec->nstlist == 0);
481                 if (bNS)
482                 {
483                     /* Generate a random position in the box */
484                     x_init[XX] = gmx_rng_uniform_real(tpi_rand)*state->box[XX][XX];
485                     x_init[YY] = gmx_rng_uniform_real(tpi_rand)*state->box[YY][YY];
486                     x_init[ZZ] = gmx_rng_uniform_real(tpi_rand)*state->box[ZZ][ZZ];
487                 }
488                 if (inputrec->nstlist == 1)
489                 {
490                     copy_rvec(x_init, x_tp);
491                 }
492                 else
493                 {
494                     /* Generate coordinates within |dx|=drmax of x_init */
495                     do
496                     {
497                         dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
498                         dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
499                         dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
500                     }
501                     while (norm2(dx) > drmax*drmax);
502                     rvec_add(x_init, dx, x_tp);
503                 }
504             }
505             else
506             {
507                 /* Random insertion around a cavity location
508                  * given by the last coordinate of the trajectory.
509                  */
510                 if (step == 0)
511                 {
512                     if (nat_cavity == 1)
513                     {
514                         /* Copy the location of the cavity */
515                         copy_rvec(rerun_fr.x[rerun_fr.natoms-1], x_init);
516                     }
517                     else
518                     {
519                         /* Determine the center of mass of the last molecule */
520                         clear_rvec(x_init);
521                         mass_tot = 0;
522                         for (i = 0; i < nat_cavity; i++)
523                         {
524                             for (d = 0; d < DIM; d++)
525                             {
526                                 x_init[d] +=
527                                     mass_cavity[i]*rerun_fr.x[rerun_fr.natoms-nat_cavity+i][d];
528                             }
529                             mass_tot += mass_cavity[i];
530                         }
531                         for (d = 0; d < DIM; d++)
532                         {
533                             x_init[d] /= mass_tot;
534                         }
535                     }
536                 }
537                 /* Generate coordinates within |dx|=drmax of x_init */
538                 do
539                 {
540                     dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
541                     dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
542                     dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
543                 }
544                 while (norm2(dx) > drmax*drmax);
545                 rvec_add(x_init, dx, x_tp);
546             }
547
548             if (a_tp1 - a_tp0 == 1)
549             {
550                 /* Insert a single atom, just copy the insertion location */
551                 copy_rvec(x_tp, state->x[a_tp0]);
552             }
553             else
554             {
555                 /* Copy the coordinates from the top file */
556                 for (i = a_tp0; i < a_tp1; i++)
557                 {
558                     copy_rvec(x_mol[i-a_tp0], state->x[i]);
559                 }
560                 /* Rotate the molecule randomly */
561                 rotate_conf(a_tp1-a_tp0, state->x+a_tp0, NULL,
562                             2*M_PI*gmx_rng_uniform_real(tpi_rand),
563                             2*M_PI*gmx_rng_uniform_real(tpi_rand),
564                             2*M_PI*gmx_rng_uniform_real(tpi_rand));
565                 /* Shift to the insertion location */
566                 for (i = a_tp0; i < a_tp1; i++)
567                 {
568                     rvec_inc(state->x[i], x_tp);
569                 }
570             }
571
572             /* Check if this insertion belongs to this node */
573             bOurStep = TRUE;
574             if (PAR(cr))
575             {
576                 switch (inputrec->eI)
577                 {
578                     case eiTPI:
579                         bOurStep = ((step / inputrec->nstlist) % nnodes == cr->nodeid);
580                         break;
581                     case eiTPIC:
582                         bOurStep = (step % nnodes == cr->nodeid);
583                         break;
584                     default:
585                         gmx_fatal(FARGS, "Unknown integrator %s", ei_names[inputrec->eI]);
586                 }
587             }
588             if (bOurStep)
589             {
590                 /* Clear some matrix variables  */
591                 clear_mat(force_vir);
592                 clear_mat(shake_vir);
593                 clear_mat(vir);
594                 clear_mat(pres);
595
596                 /* Set the charge group center of mass of the test particle */
597                 copy_rvec(x_init, fr->cg_cm[top->cgs.nr-1]);
598
599                 /* Calc energy (no forces) on new positions.
600                  * Since we only need the intermolecular energy
601                  * and the RF exclusion terms of the inserted molecule occur
602                  * within a single charge group we can pass NULL for the graph.
603                  * This also avoids shifts that would move charge groups
604                  * out of the box.
605                  *
606                  * Some checks above ensure than we can not have
607                  * twin-range interactions together with nstlist > 1,
608                  * therefore we do not need to remember the LR energies.
609                  */
610                 /* Make do_force do a single node force calculation */
611                 cr->nnodes = 1;
612                 do_force(fplog, cr, inputrec,
613                          step, nrnb, wcycle, top, &top_global->groups,
614                          state->box, state->x, &state->hist,
615                          f, force_vir, mdatoms, enerd, fcd,
616                          state->lambda,
617                          NULL, fr, NULL, mu_tot, t, NULL, NULL, FALSE,
618                          GMX_FORCE_NONBONDED | GMX_FORCE_ENERGY |
619                          (bNS ? GMX_FORCE_DYNAMICBOX | GMX_FORCE_NS | GMX_FORCE_DO_LR : 0) |
620                          (bStateChanged ? GMX_FORCE_STATECHANGED : 0));
621                 cr->nnodes    = nnodes;
622                 bStateChanged = FALSE;
623                 bNS           = FALSE;
624
625                 /* Calculate long range corrections to pressure and energy */
626                 calc_dispcorr(fplog, inputrec, fr, step, top_global->natoms, state->box,
627                               lambda, pres, vir, &prescorr, &enercorr, &dvdlcorr);
628                 /* figure out how to rearrange the next 4 lines MRS 8/4/2009 */
629                 enerd->term[F_DISPCORR]  = enercorr;
630                 enerd->term[F_EPOT]     += enercorr;
631                 enerd->term[F_PRES]     += prescorr;
632                 enerd->term[F_DVDL_VDW] += dvdlcorr;
633
634                 epot               = enerd->term[F_EPOT];
635                 bEnergyOutOfBounds = FALSE;
636 #ifdef GMX_X86_SSE2
637                 /* With SSE the energy can overflow, check for this */
638                 if (gmx_mm_check_and_reset_overflow())
639                 {
640                     if (debug)
641                     {
642                         fprintf(debug, "Found an SSE overflow, assuming the energy is out of bounds\n");
643                     }
644                     bEnergyOutOfBounds = TRUE;
645                 }
646 #endif
647                 /* If the compiler doesn't optimize this check away
648                  * we catch the NAN energies.
649                  * The epot>GMX_REAL_MAX check catches inf values,
650                  * which should nicely result in embU=0 through the exp below,
651                  * but it does not hurt to check anyhow.
652                  */
653                 /* Non-bonded Interaction usually diverge at r=0.
654                  * With tabulated interaction functions the first few entries
655                  * should be capped in a consistent fashion between
656                  * repulsion, dispersion and Coulomb to avoid accidental
657                  * negative values in the total energy.
658                  * The table generation code in tables.c does this.
659                  * With user tbales the user should take care of this.
660                  */
661                 if (epot != epot || epot > GMX_REAL_MAX)
662                 {
663                     bEnergyOutOfBounds = TRUE;
664                 }
665                 if (bEnergyOutOfBounds)
666                 {
667                     if (debug)
668                     {
669                         fprintf(debug, "\n  time %.3f, step %d: non-finite energy %f, using exp(-bU)=0\n", t, step, epot);
670                     }
671                     embU = 0;
672                 }
673                 else
674                 {
675                     embU      = exp(-beta*epot);
676                     sum_embU += embU;
677                     /* Determine the weighted energy contributions of each energy group */
678                     e                = 0;
679                     sum_UgembU[e++] += epot*embU;
680                     if (fr->bBHAM)
681                     {
682                         for (i = 0; i < ngid; i++)
683                         {
684                             sum_UgembU[e++] +=
685                                 (enerd->grpp.ener[egBHAMSR][GID(i, gid_tp, ngid)] +
686                                  enerd->grpp.ener[egBHAMLR][GID(i, gid_tp, ngid)])*embU;
687                         }
688                     }
689                     else
690                     {
691                         for (i = 0; i < ngid; i++)
692                         {
693                             sum_UgembU[e++] +=
694                                 (enerd->grpp.ener[egLJSR][GID(i, gid_tp, ngid)] +
695                                  enerd->grpp.ener[egLJLR][GID(i, gid_tp, ngid)])*embU;
696                         }
697                     }
698                     if (bDispCorr)
699                     {
700                         sum_UgembU[e++] += enerd->term[F_DISPCORR]*embU;
701                     }
702                     if (bCharge)
703                     {
704                         for (i = 0; i < ngid; i++)
705                         {
706                             sum_UgembU[e++] +=
707                                 (enerd->grpp.ener[egCOULSR][GID(i, gid_tp, ngid)] +
708                                  enerd->grpp.ener[egCOULLR][GID(i, gid_tp, ngid)])*embU;
709                         }
710                         if (bRFExcl)
711                         {
712                             sum_UgembU[e++] += enerd->term[F_RF_EXCL]*embU;
713                         }
714                         if (EEL_FULL(fr->eeltype))
715                         {
716                             sum_UgembU[e++] += enerd->term[F_COUL_RECIP]*embU;
717                         }
718                     }
719                 }
720
721                 if (embU == 0 || beta*epot > bU_bin_limit)
722                 {
723                     bin[0]++;
724                 }
725                 else
726                 {
727                     i = (int)((bU_logV_bin_limit
728                                - (beta*epot - logV + refvolshift))*invbinw
729                               + 0.5);
730                     if (i < 0)
731                     {
732                         i = 0;
733                     }
734                     if (i >= nbin)
735                     {
736                         realloc_bins(&bin, &nbin, i+10);
737                     }
738                     bin[i]++;
739                 }
740
741                 if (debug)
742                 {
743                     fprintf(debug, "TPI %7d %12.5e %12.5f %12.5f %12.5f\n",
744                             step, epot, x_tp[XX], x_tp[YY], x_tp[ZZ]);
745                 }
746
747                 if (dump_pdb && epot <= dump_ener)
748                 {
749                     sprintf(str, "t%g_step%d.pdb", t, step);
750                     sprintf(str2, "t: %f step %d ener: %f", t, step, epot);
751                     write_sto_conf_mtop(str, str2, top_global, state->x, state->v,
752                                         inputrec->ePBC, state->box);
753                 }
754             }
755         }
756
757         if (PAR(cr))
758         {
759             /* When running in parallel sum the energies over the processes */
760             gmx_sumd(1,    &sum_embU, cr);
761             gmx_sumd(nener, sum_UgembU, cr);
762         }
763
764         frame++;
765         V_all     += V;
766         VembU_all += V*sum_embU/nsteps;
767
768         if (fp_tpi)
769         {
770             if (bVerbose || frame%10 == 0 || frame < 10)
771             {
772                 fprintf(stderr, "mu %10.3e <mu> %10.3e\n",
773                         -log(sum_embU/nsteps)/beta, -log(VembU_all/V_all)/beta);
774             }
775
776             fprintf(fp_tpi, "%10.3f %12.5e %12.5e %12.5e %12.5e",
777                     t,
778                     VembU_all == 0 ? 20/beta : -log(VembU_all/V_all)/beta,
779                     sum_embU == 0  ? 20/beta : -log(sum_embU/nsteps)/beta,
780                     sum_embU/nsteps, V);
781             for (e = 0; e < nener; e++)
782             {
783                 fprintf(fp_tpi, " %12.5e", sum_UgembU[e]/nsteps);
784             }
785             fprintf(fp_tpi, "\n");
786             fflush(fp_tpi);
787         }
788
789         bNotLastFrame = read_next_frame(oenv, status, &rerun_fr);
790     } /* End of the loop  */
791     walltime_accounting_end(walltime_accounting);
792
793     close_trj(status);
794
795     if (fp_tpi != NULL)
796     {
797         gmx_fio_fclose(fp_tpi);
798     }
799
800     if (fplog != NULL)
801     {
802         fprintf(fplog, "\n");
803         fprintf(fplog, "  <V>  = %12.5e nm^3\n", V_all/frame);
804         fprintf(fplog, "  <mu> = %12.5e kJ/mol\n", -log(VembU_all/V_all)/beta);
805     }
806
807     /* Write the Boltzmann factor histogram */
808     if (PAR(cr))
809     {
810         /* When running in parallel sum the bins over the processes */
811         i = nbin;
812         global_max(cr, &i);
813         realloc_bins(&bin, &nbin, i);
814         gmx_sumd(nbin, bin, cr);
815     }
816     if (MASTER(cr))
817     {
818         fp_tpi = xvgropen(opt2fn("-tpid", nfile, fnm),
819                           "TPI energy distribution",
820                           "\\betaU - log(V/<V>)", "count", oenv);
821         sprintf(str, "number \\betaU > %g: %9.3e", bU_bin_limit, bin[0]);
822         xvgr_subtitle(fp_tpi, str, oenv);
823         xvgr_legend(fp_tpi, 2, (const char **)tpid_leg, oenv);
824         for (i = nbin-1; i > 0; i--)
825         {
826             bUlogV = -i/invbinw + bU_logV_bin_limit - refvolshift + log(V_all/frame);
827             fprintf(fp_tpi, "%6.2f %10d %12.5e\n",
828                     bUlogV,
829                     (int)(bin[i]+0.5),
830                     bin[i]*exp(-bUlogV)*V_all/VembU_all);
831         }
832         gmx_fio_fclose(fp_tpi);
833     }
834     sfree(bin);
835
836     sfree(sum_UgembU);
837
838     walltime_accounting_set_nsteps_done(walltime_accounting, frame*inputrec->nsteps);
839
840     return 0;
841 }