Improvements for energy output test.
[alexxy/gromacs.git] / src / gromacs / mdlib / energyoutput.cpp
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  * Copyright (c) 2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
7  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8  * and including many others, as listed in the AUTHORS file in the
9  * top-level source directory and at http://www.gromacs.org.
10  *
11  * GROMACS is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * as published by the Free Software Foundation; either version 2.1
14  * of the License, or (at your option) any later version.
15  *
16  * GROMACS is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with GROMACS; if not, see
23  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
25  *
26  * If you want to redistribute modifications to GROMACS, please
27  * consider that scientific software is very special. Version
28  * control is crucial - bugs must be traceable. We will be happy to
29  * consider code for inclusion in the official distribution, but
30  * derived work must not be called official GROMACS. Details are found
31  * in the README & COPYING files - if they are missing, get the
32  * official version at http://www.gromacs.org.
33  *
34  * To help us fund GROMACS development, we humbly ask that you cite
35  * the research papers on the package. Check out http://www.gromacs.org.
36  */
37 #include "gmxpre.h"
38
39 #include "energyoutput.h"
40
41 #include <cfloat>
42 #include <cstdlib>
43 #include <cstring>
44
45 #include <string>
46
47 #include "gromacs/awh/awh.h"
48 #include "gromacs/fileio/enxio.h"
49 #include "gromacs/fileio/gmxfio.h"
50 #include "gromacs/fileio/xvgr.h"
51 #include "gromacs/gmxlib/network.h"
52 #include "gromacs/listed_forces/disre.h"
53 #include "gromacs/listed_forces/orires.h"
54 #include "gromacs/math/functions.h"
55 #include "gromacs/math/units.h"
56 #include "gromacs/math/vec.h"
57 #include "gromacs/mdlib/constr.h"
58 #include "gromacs/mdlib/ebin.h"
59 #include "gromacs/mdlib/mdebin_bar.h"
60 #include "gromacs/mdtypes/energyhistory.h"
61 #include "gromacs/mdtypes/fcdata.h"
62 #include "gromacs/mdtypes/group.h"
63 #include "gromacs/mdtypes/inputrec.h"
64 #include "gromacs/mdtypes/md_enums.h"
65 #include "gromacs/mdtypes/state.h"
66 #include "gromacs/pbcutil/pbc.h"
67 #include "gromacs/pulling/pull.h"
68 #include "gromacs/topology/mtop_util.h"
69 #include "gromacs/trajectory/energyframe.h"
70 #include "gromacs/utility/arraysize.h"
71 #include "gromacs/utility/fatalerror.h"
72 #include "gromacs/utility/smalloc.h"
73 #include "gromacs/utility/stringutil.h"
74
75 static const char *conrmsd_nm[] = { "Constr. rmsd", "Constr.2 rmsd" };
76
77 static const char *boxs_nm[] = { "Box-X", "Box-Y", "Box-Z" };
78
79 static const char *tricl_boxs_nm[] = {
80     "Box-XX", "Box-YY", "Box-ZZ",
81     "Box-YX", "Box-ZX", "Box-ZY"
82 };
83
84 static const char *vol_nm[] = { "Volume" };
85
86 static const char *dens_nm[] = {"Density" };
87
88 static const char *pv_nm[] = {"pV" };
89
90 static const char *enthalpy_nm[] = {"Enthalpy" };
91
92 static const char *boxvel_nm[] = {
93     "Box-Vel-XX", "Box-Vel-YY", "Box-Vel-ZZ",
94     "Box-Vel-YX", "Box-Vel-ZX", "Box-Vel-ZY"
95 };
96
97 #define NBOXS asize(boxs_nm)
98 #define NTRICLBOXS asize(tricl_boxs_nm)
99
100 const char *egrp_nm[egNR+1] = {
101     "Coul-SR", "LJ-SR", "Buck-SR",
102     "Coul-14", "LJ-14", nullptr
103 };
104
105 /* forward declaration */
106 typedef struct t_mde_delta_h_coll t_mde_delta_h_coll;
107
108 namespace gmx
109 {
110
111 namespace detail
112 {
113
114 /* This is the collection of energy averages collected during mdrun, and to
115    be written out to the .edr file. */
116 struct t_mdebin
117 {
118     double              delta_t;
119     t_ebin             *ebin;
120     int                 ie, iconrmsd, ib, ivol, idens, ipv, ienthalpy;
121     int                 isvir, ifvir, ipres, ivir, isurft, ipc, itemp, itc, itcb, iu, imu;
122     int                 ivcos, ivisc;
123     int                 nE, nEg, nEc, nTC, nTCP, nU, nNHC;
124     int                *igrp;
125     int                 mde_n, mdeb_n;
126     real               *tmp_r;
127     rvec               *tmp_v;
128     gmx_bool            bConstr;
129     gmx_bool            bConstrVir;
130     gmx_bool            bTricl;
131     gmx_bool            bDynBox;
132     gmx_bool            bNHC_trotter;
133     gmx_bool            bPrintNHChains;
134     gmx_bool            bMTTK;
135     gmx_bool            bMu; /* true if dipole is calculated */
136     gmx_bool            bDiagPres;
137     gmx_bool            bPres;
138     int                 f_nre;
139     int                 epc;
140     real                ref_p;
141     int                 etc;
142     int                 nCrmsd;
143     gmx_bool            bEner[F_NRE];
144     gmx_bool            bEInd[egNR];
145     char              **print_grpnms;
146
147     FILE               *fp_dhdl; /* the dhdl.xvg output file */
148     double             *dE;      /* energy components for dhdl.xvg output */
149     t_mde_delta_h_coll *dhc;     /* the delta U components (raw data + histogram) */
150     real               *temperatures;
151 };
152
153 }   // namespace detail
154
155 using detail::t_mdebin;
156
157 namespace
158 {
159
160 //! Legacy init function
161 t_mdebin *init_mdebin(ener_file_t       fp_ene,
162                       const gmx_mtop_t *mtop,
163                       const t_inputrec *ir,
164                       const pull_t     *pull_work,
165                       FILE             *fp_dhdl,
166                       bool              isRerun)
167 {
168     const char                *ener_nm[F_NRE];
169     static const char         *vir_nm[] = {
170         "Vir-XX", "Vir-XY", "Vir-XZ",
171         "Vir-YX", "Vir-YY", "Vir-YZ",
172         "Vir-ZX", "Vir-ZY", "Vir-ZZ"
173     };
174     static const char         *sv_nm[] = {
175         "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ",
176         "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ",
177         "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ"
178     };
179     static const char         *fv_nm[] = {
180         "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ",
181         "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ",
182         "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ"
183     };
184     static const char         *pres_nm[] = {
185         "Pres-XX", "Pres-XY", "Pres-XZ",
186         "Pres-YX", "Pres-YY", "Pres-YZ",
187         "Pres-ZX", "Pres-ZY", "Pres-ZZ"
188     };
189     static const char         *surft_nm[] = {
190         "#Surf*SurfTen"
191     };
192     static const char         *mu_nm[] = {
193         "Mu-X", "Mu-Y", "Mu-Z"
194     };
195     static const char         *vcos_nm[] = {
196         "2CosZ*Vel-X"
197     };
198     static const char         *visc_nm[] = {
199         "1/Viscosity"
200     };
201     static const char         *baro_nm[] = {
202         "Barostat"
203     };
204
205     const SimulationGroups    *groups;
206     char                     **gnm;
207     char                       buf[256];
208     const char                *bufi;
209     t_mdebin                  *md;
210     int                        i, j, ni, nj, n, k, kk, ncon, nset;
211     gmx_bool                   bBHAM, b14;
212
213     snew(md, 1);
214
215     if (EI_DYNAMICS(ir->eI))
216     {
217         md->delta_t = ir->delta_t;
218     }
219     else
220     {
221         md->delta_t = 0;
222     }
223
224     groups = &mtop->groups;
225
226     bBHAM = (mtop->ffparams.numTypes() > 0) && (mtop->ffparams.functype[0] == F_BHAM);
227     b14   = (gmx_mtop_ftype_count(mtop, F_LJ14) > 0 ||
228              gmx_mtop_ftype_count(mtop, F_LJC14_Q) > 0);
229
230     ncon           = gmx_mtop_ftype_count(mtop, F_CONSTR);
231     nset           = gmx_mtop_ftype_count(mtop, F_SETTLE);
232     md->bConstr    = (ncon > 0 || nset > 0) && !isRerun;
233     md->bConstrVir = FALSE;
234     if (md->bConstr)
235     {
236         if (ncon > 0 && ir->eConstrAlg == econtLINCS)
237         {
238             md->nCrmsd = 1;
239         }
240         md->bConstrVir = (getenv("GMX_CONSTRAINTVIR") != nullptr);
241     }
242     else
243     {
244         md->nCrmsd = 0;
245     }
246
247     /* Energy monitoring */
248     for (i = 0; i < egNR; i++)
249     {
250         md->bEInd[i] = FALSE;
251     }
252
253     for (i = 0; i < F_NRE; i++)
254     {
255         md->bEner[i] = FALSE;
256         if (isRerun &&
257             (i == F_EKIN || i == F_ETOT || i == F_ECONSERVED ||
258              i == F_TEMP || i == F_PDISPCORR || i == F_PRES))
259         {
260             continue;
261         }
262         if (i == F_LJ)
263         {
264             md->bEner[i] = !bBHAM;
265         }
266         else if (i == F_BHAM)
267         {
268             md->bEner[i] = bBHAM;
269         }
270         else if (i == F_EQM)
271         {
272             md->bEner[i] = ir->bQMMM;
273         }
274         else if (i == F_RF_EXCL)
275         {
276             md->bEner[i] = (EEL_RF(ir->coulombtype) && ir->cutoff_scheme == ecutsGROUP);
277         }
278         else if (i == F_COUL_RECIP)
279         {
280             md->bEner[i] = EEL_FULL(ir->coulombtype);
281         }
282         else if (i == F_LJ_RECIP)
283         {
284             md->bEner[i] = EVDW_PME(ir->vdwtype);
285         }
286         else if (i == F_LJ14)
287         {
288             md->bEner[i] = b14;
289         }
290         else if (i == F_COUL14)
291         {
292             md->bEner[i] = b14;
293         }
294         else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB)
295         {
296             md->bEner[i] = FALSE;
297         }
298         else if ((i == F_DVDL_COUL && ir->fepvals->separate_dvdl[efptCOUL]) ||
299                  (i == F_DVDL_VDW  && ir->fepvals->separate_dvdl[efptVDW]) ||
300                  (i == F_DVDL_BONDED && ir->fepvals->separate_dvdl[efptBONDED]) ||
301                  (i == F_DVDL_RESTRAINT && ir->fepvals->separate_dvdl[efptRESTRAINT]) ||
302                  (i == F_DKDL && ir->fepvals->separate_dvdl[efptMASS]) ||
303                  (i == F_DVDL && ir->fepvals->separate_dvdl[efptFEP]))
304         {
305             md->bEner[i] = (ir->efep != efepNO);
306         }
307         else if ((interaction_function[i].flags & IF_VSITE) ||
308                  (i == F_CONSTR) || (i == F_CONSTRNC) || (i == F_SETTLE))
309         {
310             md->bEner[i] = FALSE;
311         }
312         else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES)  || (i == F_EQM))
313         {
314             md->bEner[i] = TRUE;
315         }
316         else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP))
317         {
318             md->bEner[i] = EI_DYNAMICS(ir->eI);
319         }
320         else if (i == F_DISPCORR || i == F_PDISPCORR)
321         {
322             md->bEner[i] = (ir->eDispCorr != edispcNO);
323         }
324         else if (i == F_DISRESVIOL)
325         {
326             md->bEner[i] = (gmx_mtop_ftype_count(mtop, F_DISRES) > 0);
327         }
328         else if (i == F_ORIRESDEV)
329         {
330             md->bEner[i] = (gmx_mtop_ftype_count(mtop, F_ORIRES) > 0);
331         }
332         else if (i == F_CONNBONDS)
333         {
334             md->bEner[i] = FALSE;
335         }
336         else if (i == F_COM_PULL)
337         {
338             md->bEner[i] = ((ir->bPull && pull_have_potential(pull_work)) ||
339                             ir->bRot);
340         }
341         else if (i == F_ECONSERVED)
342         {
343             md->bEner[i] = (integratorHasConservedEnergyQuantity(ir));
344         }
345         else
346         {
347             md->bEner[i] = (gmx_mtop_ftype_count(mtop, i) > 0);
348         }
349     }
350
351     md->f_nre = 0;
352     for (i = 0; i < F_NRE; i++)
353     {
354         if (md->bEner[i])
355         {
356             ener_nm[md->f_nre] = interaction_function[i].longname;
357             md->f_nre++;
358         }
359     }
360
361     md->epc            = isRerun ? epcNO : ir->epc;
362     md->bDiagPres      = !TRICLINIC(ir->ref_p) && !isRerun;
363     md->ref_p          = (ir->ref_p[XX][XX]+ir->ref_p[YY][YY]+ir->ref_p[ZZ][ZZ])/DIM;
364     md->bTricl         = TRICLINIC(ir->compress) || TRICLINIC(ir->deform);
365     md->bDynBox        = inputrecDynamicBox(ir);
366     md->etc            = isRerun ? etcNO : ir->etc;
367     md->bNHC_trotter   = inputrecNvtTrotter(ir) && !isRerun;
368     md->bPrintNHChains = ir->bPrintNHChains && !isRerun;
369     md->bMTTK          = (inputrecNptTrotter(ir) || inputrecNphTrotter(ir)) && !isRerun;
370     md->bMu            = inputrecNeedMutot(ir);
371     md->bPres          = !isRerun;
372
373     md->ebin  = mk_ebin();
374     /* Pass NULL for unit to let get_ebin_space determine the units
375      * for interaction_function[i].longname
376      */
377     md->ie    = get_ebin_space(md->ebin, md->f_nre, ener_nm, nullptr);
378     if (md->nCrmsd)
379     {
380         /* This should be called directly after the call for md->ie,
381          * such that md->iconrmsd follows directly in the list.
382          */
383         md->iconrmsd = get_ebin_space(md->ebin, md->nCrmsd, conrmsd_nm, "");
384     }
385     if (md->bDynBox)
386     {
387         md->ib    = get_ebin_space(md->ebin,
388                                    md->bTricl ? NTRICLBOXS : NBOXS,
389                                    md->bTricl ? tricl_boxs_nm : boxs_nm,
390                                    unit_length);
391         md->ivol  = get_ebin_space(md->ebin, 1, vol_nm,  unit_volume);
392         md->idens = get_ebin_space(md->ebin, 1, dens_nm, unit_density_SI);
393         if (md->bDiagPres)
394         {
395             md->ipv       = get_ebin_space(md->ebin, 1, pv_nm,   unit_energy);
396             md->ienthalpy = get_ebin_space(md->ebin, 1, enthalpy_nm,   unit_energy);
397         }
398     }
399     if (md->bConstrVir)
400     {
401         md->isvir = get_ebin_space(md->ebin, asize(sv_nm), sv_nm, unit_energy);
402         md->ifvir = get_ebin_space(md->ebin, asize(fv_nm), fv_nm, unit_energy);
403     }
404     if (md->bPres)
405     {
406         md->ivir   = get_ebin_space(md->ebin, asize(vir_nm), vir_nm, unit_energy);
407         md->ipres  = get_ebin_space(md->ebin, asize(pres_nm), pres_nm, unit_pres_bar);
408         md->isurft = get_ebin_space(md->ebin, asize(surft_nm), surft_nm,
409                                     unit_surft_bar);
410     }
411     if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK)
412     {
413         md->ipc = get_ebin_space(md->ebin, md->bTricl ? 6 : 3,
414                                  boxvel_nm, unit_vel);
415     }
416     if (md->bMu)
417     {
418         md->imu    = get_ebin_space(md->ebin, asize(mu_nm), mu_nm, unit_dipole_D);
419     }
420     if (ir->cos_accel != 0)
421     {
422         md->ivcos = get_ebin_space(md->ebin, asize(vcos_nm), vcos_nm, unit_vel);
423         md->ivisc = get_ebin_space(md->ebin, asize(visc_nm), visc_nm,
424                                    unit_invvisc_SI);
425     }
426
427     /* Energy monitoring */
428     for (i = 0; i < egNR; i++)
429     {
430         md->bEInd[i] = FALSE;
431     }
432     md->bEInd[egCOULSR] = TRUE;
433     md->bEInd[egLJSR  ] = TRUE;
434
435     if (bBHAM)
436     {
437         md->bEInd[egLJSR]   = FALSE;
438         md->bEInd[egBHAMSR] = TRUE;
439     }
440     if (b14)
441     {
442         md->bEInd[egLJ14]   = TRUE;
443         md->bEInd[egCOUL14] = TRUE;
444     }
445     md->nEc = 0;
446     for (i = 0; (i < egNR); i++)
447     {
448         if (md->bEInd[i])
449         {
450             md->nEc++;
451         }
452     }
453     n       = groups->groups[SimulationAtomGroupType::EnergyOutput].nr;
454     md->nEg = n;
455     md->nE  = (n*(n+1))/2;
456
457     snew(md->igrp, md->nE);
458     if (md->nE > 1)
459     {
460         n = 0;
461         snew(gnm, md->nEc);
462         for (k = 0; (k < md->nEc); k++)
463         {
464             snew(gnm[k], STRLEN);
465         }
466         for (i = 0; (i < groups->groups[SimulationAtomGroupType::EnergyOutput].nr); i++)
467         {
468             ni = groups->groups[SimulationAtomGroupType::EnergyOutput].nm_ind[i];
469             for (j = i; (j < groups->groups[SimulationAtomGroupType::EnergyOutput].nr); j++)
470             {
471                 nj = groups->groups[SimulationAtomGroupType::EnergyOutput].nm_ind[j];
472                 for (k = kk = 0; (k < egNR); k++)
473                 {
474                     if (md->bEInd[k])
475                     {
476                         sprintf(gnm[kk], "%s:%s-%s", egrp_nm[k],
477                                 *(groups->groupNames[ni]), *(groups->groupNames[nj]));
478                         kk++;
479                     }
480                 }
481                 md->igrp[n] = get_ebin_space(md->ebin, md->nEc,
482                                              gnm, unit_energy);
483                 n++;
484             }
485         }
486         for (k = 0; (k < md->nEc); k++)
487         {
488             sfree(gnm[k]);
489         }
490         sfree(gnm);
491
492         if (n != md->nE)
493         {
494             gmx_incons("Number of energy terms wrong");
495         }
496     }
497
498     md->nTC  = isRerun ? 0 : groups->groups[SimulationAtomGroupType::TemperatureCoupling].nr;
499     md->nNHC = ir->opts.nhchainlength; /* shorthand for number of NH chains */
500     if (md->bMTTK)
501     {
502         md->nTCP = 1;  /* assume only one possible coupling system for barostat
503                           for now */
504     }
505     else
506     {
507         md->nTCP = 0;
508     }
509     if (md->etc == etcNOSEHOOVER)
510     {
511         if (md->bNHC_trotter)
512         {
513             md->mde_n = 2*md->nNHC*md->nTC;
514         }
515         else
516         {
517             md->mde_n = 2*md->nTC;
518         }
519         if (md->epc == epcMTTK)
520         {
521             md->mdeb_n = 2*md->nNHC*md->nTCP;
522         }
523     }
524     else
525     {
526         md->mde_n  = md->nTC;
527         md->mdeb_n = 0;
528     }
529
530     snew(md->tmp_r, md->mde_n);
531     snew(md->tmp_v, md->mde_n);
532     // TODO redo the group name memory management to make it more clear
533     char **grpnms;
534     snew(grpnms, std::max(md->mde_n, md->mdeb_n)); // Just in case md->mdeb_n > md->mde_n
535
536     for (i = 0; (i < md->nTC); i++)
537     {
538         ni = groups->groups[SimulationAtomGroupType::TemperatureCoupling].nm_ind[i];
539         sprintf(buf, "T-%s", *(groups->groupNames[ni]));
540         grpnms[i] = gmx_strdup(buf);
541     }
542     md->itemp = get_ebin_space(md->ebin, md->nTC, grpnms,
543                                unit_temp_K);
544     for (i = 0; i < md->nTC; i++)
545     {
546         sfree(grpnms[i]);
547     }
548
549     int allocated = 0;
550     if (md->etc == etcNOSEHOOVER)
551     {
552         if (md->bPrintNHChains)
553         {
554             if (md->bNHC_trotter)
555             {
556                 for (i = 0; (i < md->nTC); i++)
557                 {
558                     ni   = groups->groups[SimulationAtomGroupType::TemperatureCoupling].nm_ind[i];
559                     bufi = *(groups->groupNames[ni]);
560                     for (j = 0; (j < md->nNHC); j++)
561                     {
562                         sprintf(buf, "Xi-%d-%s", j, bufi);
563                         grpnms[2*(i*md->nNHC+j)] = gmx_strdup(buf);
564                         sprintf(buf, "vXi-%d-%s", j, bufi);
565                         grpnms[2*(i*md->nNHC+j)+1] = gmx_strdup(buf);
566                     }
567                 }
568                 md->itc = get_ebin_space(md->ebin, md->mde_n,
569                                          grpnms, unit_invtime);
570                 allocated = md->mde_n;
571                 if (md->bMTTK)
572                 {
573                     for (i = 0; (i < md->nTCP); i++)
574                     {
575                         bufi = baro_nm[0];  /* All barostat DOF's together for now. */
576                         for (j = 0; (j < md->nNHC); j++)
577                         {
578                             sprintf(buf, "Xi-%d-%s", j, bufi);
579                             grpnms[2*(i*md->nNHC+j)] = gmx_strdup(buf);
580                             sprintf(buf, "vXi-%d-%s", j, bufi);
581                             grpnms[2*(i*md->nNHC+j)+1] = gmx_strdup(buf);
582                         }
583                     }
584                     md->itcb = get_ebin_space(md->ebin, md->mdeb_n,
585                                               grpnms, unit_invtime);
586                     allocated = md->mdeb_n;
587                 }
588             }
589             else
590             {
591                 for (i = 0; (i < md->nTC); i++)
592                 {
593                     ni   = groups->groups[SimulationAtomGroupType::TemperatureCoupling].nm_ind[i];
594                     bufi = *(groups->groupNames[ni]);
595                     sprintf(buf, "Xi-%s", bufi);
596                     grpnms[2*i] = gmx_strdup(buf);
597                     sprintf(buf, "vXi-%s", bufi);
598                     grpnms[2*i+1] = gmx_strdup(buf);
599                 }
600                 md->itc = get_ebin_space(md->ebin, md->mde_n,
601                                          grpnms, unit_invtime);
602                 allocated = md->mde_n;
603             }
604         }
605     }
606     else if (md->etc == etcBERENDSEN || md->etc == etcYES ||
607              md->etc == etcVRESCALE)
608     {
609         for (i = 0; (i < md->nTC); i++)
610         {
611             ni = groups->groups[SimulationAtomGroupType::TemperatureCoupling].nm_ind[i];
612             sprintf(buf, "Lamb-%s", *(groups->groupNames[ni]));
613             grpnms[i] = gmx_strdup(buf);
614         }
615         md->itc   = get_ebin_space(md->ebin, md->mde_n, grpnms, "");
616         allocated = md->mde_n;
617     }
618
619     for (i = 0; i < allocated; i++)
620     {
621         sfree(grpnms[i]);
622     }
623     sfree(grpnms);
624
625     md->nU = groups->groups[SimulationAtomGroupType::Acceleration].nr;
626     if (md->nU > 1)
627     {
628         snew(grpnms, 3*md->nU);
629         for (i = 0; (i < md->nU); i++)
630         {
631             ni = groups->groups[SimulationAtomGroupType::Acceleration].nm_ind[i];
632             sprintf(buf, "Ux-%s", *(groups->groupNames[ni]));
633             grpnms[3*i+XX] = gmx_strdup(buf);
634             sprintf(buf, "Uy-%s", *(groups->groupNames[ni]));
635             grpnms[3*i+YY] = gmx_strdup(buf);
636             sprintf(buf, "Uz-%s", *(groups->groupNames[ni]));
637             grpnms[3*i+ZZ] = gmx_strdup(buf);
638         }
639         md->iu = get_ebin_space(md->ebin, 3*md->nU, grpnms, unit_vel);
640         for (i = 0; i < 3*md->nU; i++)
641         {
642             sfree(grpnms[i]);
643         }
644         sfree(grpnms);
645     }
646
647     if (fp_ene)
648     {
649         do_enxnms(fp_ene, &md->ebin->nener, &md->ebin->enm);
650     }
651
652     md->print_grpnms = nullptr;
653
654     /* check whether we're going to write dh histograms */
655     md->dhc = nullptr;
656     if (ir->fepvals->separate_dhdl_file == esepdhdlfileNO)
657     {
658         /* Currently dh histograms are only written with dynamics */
659         if (EI_DYNAMICS(ir->eI))
660         {
661             snew(md->dhc, 1);
662
663             mde_delta_h_coll_init(md->dhc, ir);
664         }
665         md->fp_dhdl = nullptr;
666         snew(md->dE, ir->fepvals->n_lambda);
667     }
668     else
669     {
670         md->fp_dhdl = fp_dhdl;
671         snew(md->dE, ir->fepvals->n_lambda);
672     }
673     if (ir->bSimTemp)
674     {
675         int i;
676         snew(md->temperatures, ir->fepvals->n_lambda);
677         for (i = 0; i < ir->fepvals->n_lambda; i++)
678         {
679             md->temperatures[i] = ir->simtempvals->temperatures[i];
680         }
681     }
682     return md;
683 }
684
685 //! Legacy cleanup function
686 void done_mdebin(t_mdebin *mdebin)
687 {
688     sfree(mdebin->igrp);
689     sfree(mdebin->tmp_r);
690     sfree(mdebin->tmp_v);
691     done_ebin(mdebin->ebin);
692     done_mde_delta_h_coll(mdebin->dhc);
693     sfree(mdebin->dE);
694     sfree(mdebin->temperatures);
695     if (mdebin->nE > 1 && mdebin->print_grpnms != nullptr)
696     {
697         for (int n = 0; n < mdebin->nE; n++)
698         {
699             sfree(mdebin->print_grpnms[n]);
700         }
701         sfree(mdebin->print_grpnms);
702     }
703     sfree(mdebin);
704 }
705
706 } // namespace
707 } // namespace gmx
708
709 /* print a lambda vector to a string
710    fep = the inputrec's FEP input data
711    i = the index of the lambda vector
712    get_native_lambda = whether to print the native lambda
713    get_names = whether to print the names rather than the values
714    str = the pre-allocated string buffer to print to. */
715 static void print_lambda_vector(t_lambda *fep, int i,
716                                 gmx_bool get_native_lambda, gmx_bool get_names,
717                                 char *str)
718 {
719     int    j, k = 0;
720     int    Nsep = 0;
721
722     for (j = 0; j < efptNR; j++)
723     {
724         if (fep->separate_dvdl[j])
725         {
726             Nsep++;
727         }
728     }
729     str[0] = 0; /* reset the string */
730     if (Nsep > 1)
731     {
732         str += sprintf(str, "("); /* set the opening parenthesis*/
733     }
734     for (j = 0; j < efptNR; j++)
735     {
736         if (fep->separate_dvdl[j])
737         {
738             if (!get_names)
739             {
740                 if (get_native_lambda && fep->init_lambda >= 0)
741                 {
742                     str += sprintf(str, "%.4f", fep->init_lambda);
743                 }
744                 else
745                 {
746                     str += sprintf(str, "%.4f", fep->all_lambda[j][i]);
747                 }
748             }
749             else
750             {
751                 str += sprintf(str, "%s", efpt_singular_names[j]);
752             }
753             /* print comma for the next item */
754             if (k < Nsep-1)
755             {
756                 str += sprintf(str, ", ");
757             }
758             k++;
759         }
760     }
761     if (Nsep > 1)
762     {
763         /* and add the closing parenthesis */
764         sprintf(str, ")");
765     }
766 }
767
768 FILE *open_dhdl(const char *filename, const t_inputrec *ir,
769                 const gmx_output_env_t *oenv)
770 {
771     FILE       *fp;
772     const char *dhdl = "dH/d\\lambda", *deltag = "\\DeltaH", *lambda = "\\lambda",
773     *lambdastate     = "\\lambda state";
774     int         i, nsets, nsets_de, nsetsbegin;
775     int         n_lambda_terms = 0;
776     t_lambda   *fep            = ir->fepvals; /* for simplicity */
777     t_expanded *expand         = ir->expandedvals;
778     char        lambda_vec_str[STRLEN], lambda_name_str[STRLEN];
779
780     int         nsets_dhdl = 0;
781     int         s          = 0;
782     int         nsetsextend;
783     gmx_bool    write_pV = FALSE;
784
785     /* count the number of different lambda terms */
786     for (i = 0; i < efptNR; i++)
787     {
788         if (fep->separate_dvdl[i])
789         {
790             n_lambda_terms++;
791         }
792     }
793
794     std::string title, label_x, label_y;
795     if (fep->n_lambda == 0)
796     {
797         title   = gmx::formatString("%s", dhdl);
798         label_x = gmx::formatString("Time (ps)");
799         label_y = gmx::formatString("%s (%s %s)",
800                                     dhdl, unit_energy, "[\\lambda]\\S-1\\N");
801     }
802     else
803     {
804         title   = gmx::formatString("%s and %s", dhdl, deltag);
805         label_x = gmx::formatString("Time (ps)");
806         label_y = gmx::formatString("%s and %s (%s %s)",
807                                     dhdl, deltag, unit_energy, "[\\8l\\4]\\S-1\\N");
808     }
809     fp = gmx_fio_fopen(filename, "w+");
810     xvgr_header(fp, title.c_str(), label_x, label_y, exvggtXNY, oenv);
811
812     std::string buf;
813     if (!(ir->bSimTemp))
814     {
815         buf = gmx::formatString("T = %g (K) ", ir->opts.ref_t[0]);
816     }
817     if ((ir->efep != efepSLOWGROWTH) && (ir->efep != efepEXPANDED))
818     {
819         if ( (fep->init_lambda >= 0)  && (n_lambda_terms == 1 ))
820         {
821             /* compatibility output */
822             buf += gmx::formatString("%s = %.4f", lambda, fep->init_lambda);
823         }
824         else
825         {
826             print_lambda_vector(fep, fep->init_fep_state, TRUE, FALSE,
827                                 lambda_vec_str);
828             print_lambda_vector(fep, fep->init_fep_state, TRUE, TRUE,
829                                 lambda_name_str);
830             buf += gmx::formatString("%s %d: %s = %s",
831                                      lambdastate, fep->init_fep_state,
832                                      lambda_name_str, lambda_vec_str);
833         }
834     }
835     xvgr_subtitle(fp, buf.c_str(), oenv);
836
837
838     nsets_dhdl = 0;
839     if (fep->dhdl_derivatives == edhdlderivativesYES)
840     {
841         nsets_dhdl = n_lambda_terms;
842     }
843     /* count the number of delta_g states */
844     nsets_de = fep->lambda_stop_n - fep->lambda_start_n;
845
846     nsets = nsets_dhdl + nsets_de; /* dhdl + fep differences */
847
848     if (fep->n_lambda > 0 && (expand->elmcmove > elmcmoveNO))
849     {
850         nsets += 1;   /*add fep state for expanded ensemble */
851     }
852
853     if (fep->edHdLPrintEnergy != edHdLPrintEnergyNO)
854     {
855         nsets += 1;  /* add energy to the dhdl as well */
856     }
857
858     nsetsextend = nsets;
859     if ((ir->epc != epcNO) && (fep->n_lambda > 0) && (fep->init_lambda < 0))
860     {
861         nsetsextend += 1; /* for PV term, other terms possible if required for
862                              the reduced potential (only needed with foreign
863                              lambda, and only output when init_lambda is not
864                              set in order to maintain compatibility of the
865                              dhdl.xvg file) */
866         write_pV     = TRUE;
867     }
868     std::vector<std::string> setname(nsetsextend);
869
870     if (expand->elmcmove > elmcmoveNO)
871     {
872         /* state for the fep_vals, if we have alchemical sampling */
873         setname[s++] = "Thermodynamic state";
874     }
875
876     if (fep->edHdLPrintEnergy != edHdLPrintEnergyNO)
877     {
878         std::string energy;
879         switch (fep->edHdLPrintEnergy)
880         {
881             case edHdLPrintEnergyPOTENTIAL:
882                 energy = gmx::formatString("%s (%s)", "Potential Energy", unit_energy);
883                 break;
884             case edHdLPrintEnergyTOTAL:
885             case edHdLPrintEnergyYES:
886             default:
887                 energy = gmx::formatString("%s (%s)", "Total Energy", unit_energy);
888         }
889         setname[s++] = energy;
890     }
891
892     if (fep->dhdl_derivatives == edhdlderivativesYES)
893     {
894         for (i = 0; i < efptNR; i++)
895         {
896             if (fep->separate_dvdl[i])
897             {
898                 std::string derivative;
899                 if ( (fep->init_lambda >= 0)  && (n_lambda_terms == 1 ))
900                 {
901                     /* compatibility output */
902                     derivative = gmx::formatString("%s %s %.4f", dhdl, lambda, fep->init_lambda);
903                 }
904                 else
905                 {
906                     double lam = fep->init_lambda;
907                     if (fep->init_lambda < 0)
908                     {
909                         lam = fep->all_lambda[i][fep->init_fep_state];
910                     }
911                     derivative = gmx::formatString("%s %s = %.4f", dhdl, efpt_singular_names[i],
912                                                    lam);
913                 }
914                 setname[s++] = derivative;
915             }
916         }
917     }
918
919     if (fep->n_lambda > 0)
920     {
921         /* g_bar has to determine the lambda values used in this simulation
922          * from this xvg legend.
923          */
924
925         if (expand->elmcmove > elmcmoveNO)
926         {
927             nsetsbegin = 1;  /* for including the expanded ensemble */
928         }
929         else
930         {
931             nsetsbegin = 0;
932         }
933
934         if (fep->edHdLPrintEnergy != edHdLPrintEnergyNO)
935         {
936             nsetsbegin += 1;
937         }
938         nsetsbegin += nsets_dhdl;
939
940         for (i = fep->lambda_start_n; i < fep->lambda_stop_n; i++)
941         {
942             print_lambda_vector(fep, i, FALSE, FALSE, lambda_vec_str);
943             std::string buf;
944             if ( (fep->init_lambda >= 0)  && (n_lambda_terms == 1 ))
945             {
946                 /* for compatible dhdl.xvg files */
947                 buf = gmx::formatString("%s %s %s", deltag, lambda, lambda_vec_str);
948             }
949             else
950             {
951                 buf = gmx::formatString("%s %s to %s", deltag, lambda, lambda_vec_str);
952             }
953
954             if (ir->bSimTemp)
955             {
956                 /* print the temperature for this state if doing simulated annealing */
957                 buf += gmx::formatString("T = %g (%s)",
958                                          ir->simtempvals->temperatures[s-(nsetsbegin)],
959                                          unit_temp_K);
960             }
961             setname[s++] = buf;
962         }
963         if (write_pV)
964         {
965             setname[s++] = gmx::formatString("pV (%s)", unit_energy);
966         }
967
968         xvgrLegend(fp, setname, oenv);
969     }
970
971     return fp;
972 }
973
974 namespace gmx
975 {
976 namespace
977 {
978
979 //! Legacy update function
980 void upd_mdebin(t_mdebin               *md,
981                 gmx_bool                bDoDHDL,
982                 gmx_bool                bSum,
983                 double                  time,
984                 real                    tmass,
985                 gmx_enerdata_t         *enerd,
986                 t_state                *state,
987                 t_lambda               *fep,
988                 t_expanded             *expand,
989                 matrix                  box,
990                 tensor                  svir,
991                 tensor                  fvir,
992                 tensor                  vir,
993                 tensor                  pres,
994                 gmx_ekindata_t         *ekind,
995                 rvec                    mu_tot,
996                 const gmx::Constraints *constr)
997 {
998     int    i, j, k, kk, n, gid;
999     real   crmsd[2], tmp6[6];
1000     real   bs[NTRICLBOXS], vol, dens, pv, enthalpy;
1001     real   eee[egNR];
1002     double store_dhdl[efptNR];
1003     real   store_energy = 0;
1004     real   tmp;
1005
1006     /* Do NOT use the box in the state variable, but the separate box provided
1007      * as an argument. This is because we sometimes need to write the box from
1008      * the last timestep to match the trajectory frames.
1009      */
1010     add_ebin_indexed(md->ebin, md->ie, gmx::ArrayRef<gmx_bool>(md->bEner), enerd->term, bSum);
1011     if (md->nCrmsd)
1012     {
1013         crmsd[0] = constr->rmsd();
1014         add_ebin(md->ebin, md->iconrmsd, md->nCrmsd, crmsd, FALSE);
1015     }
1016     if (md->bDynBox)
1017     {
1018         int nboxs;
1019         if (md->bTricl)
1020         {
1021             bs[0] = box[XX][XX];
1022             bs[1] = box[YY][YY];
1023             bs[2] = box[ZZ][ZZ];
1024             bs[3] = box[YY][XX];
1025             bs[4] = box[ZZ][XX];
1026             bs[5] = box[ZZ][YY];
1027             nboxs = NTRICLBOXS;
1028         }
1029         else
1030         {
1031             bs[0] = box[XX][XX];
1032             bs[1] = box[YY][YY];
1033             bs[2] = box[ZZ][ZZ];
1034             nboxs = NBOXS;
1035         }
1036         vol  = box[XX][XX]*box[YY][YY]*box[ZZ][ZZ];
1037         dens = (tmass*AMU)/(vol*NANO*NANO*NANO);
1038         add_ebin(md->ebin, md->ib, nboxs, bs, bSum);
1039         add_ebin(md->ebin, md->ivol, 1, &vol, bSum);
1040         add_ebin(md->ebin, md->idens, 1, &dens, bSum);
1041
1042         if (md->bDiagPres)
1043         {
1044             /* This is pV (in kJ/mol).  The pressure is the reference pressure,
1045                not the instantaneous pressure */
1046             pv = vol*md->ref_p/PRESFAC;
1047
1048             add_ebin(md->ebin, md->ipv, 1, &pv, bSum);
1049             enthalpy = pv + enerd->term[F_ETOT];
1050             add_ebin(md->ebin, md->ienthalpy, 1, &enthalpy, bSum);
1051         }
1052     }
1053     if (md->bConstrVir)
1054     {
1055         add_ebin(md->ebin, md->isvir, 9, svir[0], bSum);
1056         add_ebin(md->ebin, md->ifvir, 9, fvir[0], bSum);
1057     }
1058     if (md->bPres)
1059     {
1060         add_ebin(md->ebin, md->ivir, 9, vir[0], bSum);
1061         add_ebin(md->ebin, md->ipres, 9, pres[0], bSum);
1062         tmp = (pres[ZZ][ZZ]-(pres[XX][XX]+pres[YY][YY])*0.5)*box[ZZ][ZZ];
1063         add_ebin(md->ebin, md->isurft, 1, &tmp, bSum);
1064     }
1065     if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK)
1066     {
1067         tmp6[0] = state->boxv[XX][XX];
1068         tmp6[1] = state->boxv[YY][YY];
1069         tmp6[2] = state->boxv[ZZ][ZZ];
1070         tmp6[3] = state->boxv[YY][XX];
1071         tmp6[4] = state->boxv[ZZ][XX];
1072         tmp6[5] = state->boxv[ZZ][YY];
1073         add_ebin(md->ebin, md->ipc, md->bTricl ? 6 : 3, tmp6, bSum);
1074     }
1075     if (md->bMu)
1076     {
1077         add_ebin(md->ebin, md->imu, 3, mu_tot, bSum);
1078     }
1079     if (ekind && ekind->cosacc.cos_accel != 0)
1080     {
1081         vol  = box[XX][XX]*box[YY][YY]*box[ZZ][ZZ];
1082         dens = (tmass*AMU)/(vol*NANO*NANO*NANO);
1083         add_ebin(md->ebin, md->ivcos, 1, &(ekind->cosacc.vcos), bSum);
1084         /* 1/viscosity, unit 1/(kg m^-1 s^-1) */
1085         tmp = 1/(ekind->cosacc.cos_accel/(ekind->cosacc.vcos*PICO)
1086                  *dens*gmx::square(box[ZZ][ZZ]*NANO/(2*M_PI)));
1087         add_ebin(md->ebin, md->ivisc, 1, &tmp, bSum);
1088     }
1089     if (md->nE > 1)
1090     {
1091         n = 0;
1092         for (i = 0; (i < md->nEg); i++)
1093         {
1094             for (j = i; (j < md->nEg); j++)
1095             {
1096                 gid = GID(i, j, md->nEg);
1097                 for (k = kk = 0; (k < egNR); k++)
1098                 {
1099                     if (md->bEInd[k])
1100                     {
1101                         eee[kk++] = enerd->grpp.ener[k][gid];
1102                     }
1103                 }
1104                 add_ebin(md->ebin, md->igrp[n], md->nEc, eee, bSum);
1105                 n++;
1106             }
1107         }
1108     }
1109
1110     if (ekind)
1111     {
1112         for (i = 0; (i < md->nTC); i++)
1113         {
1114             md->tmp_r[i] = ekind->tcstat[i].T;
1115         }
1116         add_ebin(md->ebin, md->itemp, md->nTC, md->tmp_r, bSum);
1117
1118         if (md->etc == etcNOSEHOOVER)
1119         {
1120             /* whether to print Nose-Hoover chains: */
1121             if (md->bPrintNHChains)
1122             {
1123                 if (md->bNHC_trotter)
1124                 {
1125                     for (i = 0; (i < md->nTC); i++)
1126                     {
1127                         for (j = 0; j < md->nNHC; j++)
1128                         {
1129                             k                = i*md->nNHC+j;
1130                             md->tmp_r[2*k]   = state->nosehoover_xi[k];
1131                             md->tmp_r[2*k+1] = state->nosehoover_vxi[k];
1132                         }
1133                     }
1134                     add_ebin(md->ebin, md->itc, md->mde_n, md->tmp_r, bSum);
1135
1136                     if (md->bMTTK)
1137                     {
1138                         for (i = 0; (i < md->nTCP); i++)
1139                         {
1140                             for (j = 0; j < md->nNHC; j++)
1141                             {
1142                                 k                = i*md->nNHC+j;
1143                                 md->tmp_r[2*k]   = state->nhpres_xi[k];
1144                                 md->tmp_r[2*k+1] = state->nhpres_vxi[k];
1145                             }
1146                         }
1147                         add_ebin(md->ebin, md->itcb, md->mdeb_n, md->tmp_r, bSum);
1148                     }
1149                 }
1150                 else
1151                 {
1152                     for (i = 0; (i < md->nTC); i++)
1153                     {
1154                         md->tmp_r[2*i]   = state->nosehoover_xi[i];
1155                         md->tmp_r[2*i+1] = state->nosehoover_vxi[i];
1156                     }
1157                     add_ebin(md->ebin, md->itc, md->mde_n, md->tmp_r, bSum);
1158                 }
1159             }
1160         }
1161         else if (md->etc == etcBERENDSEN || md->etc == etcYES ||
1162                  md->etc == etcVRESCALE)
1163         {
1164             for (i = 0; (i < md->nTC); i++)
1165             {
1166                 md->tmp_r[i] = ekind->tcstat[i].lambda;
1167             }
1168             add_ebin(md->ebin, md->itc, md->nTC, md->tmp_r, bSum);
1169         }
1170     }
1171
1172     if (ekind && md->nU > 1)
1173     {
1174         for (i = 0; (i < md->nU); i++)
1175         {
1176             copy_rvec(ekind->grpstat[i].u, md->tmp_v[i]);
1177         }
1178         add_ebin(md->ebin, md->iu, 3*md->nU, md->tmp_v[0], bSum);
1179     }
1180
1181     ebin_increase_count(md->ebin, bSum);
1182
1183     /* BAR + thermodynamic integration values */
1184     if ((md->fp_dhdl || md->dhc) && bDoDHDL)
1185     {
1186         for (i = 0; i < enerd->n_lambda-1; i++)
1187         {
1188             /* zero for simulated tempering */
1189             md->dE[i] = enerd->enerpart_lambda[i+1]-enerd->enerpart_lambda[0];
1190             if (md->temperatures != nullptr)
1191             {
1192                 /* MRS: is this right, given the way we have defined the exchange probabilities? */
1193                 /* is this even useful to have at all? */
1194                 md->dE[i] += (md->temperatures[i]/
1195                               md->temperatures[state->fep_state]-1.0)*
1196                     enerd->term[F_EKIN];
1197             }
1198         }
1199
1200         if (md->fp_dhdl)
1201         {
1202             fprintf(md->fp_dhdl, "%.4f", time);
1203             /* the current free energy state */
1204
1205             /* print the current state if we are doing expanded ensemble */
1206             if (expand->elmcmove > elmcmoveNO)
1207             {
1208                 fprintf(md->fp_dhdl, " %4d", state->fep_state);
1209             }
1210             /* total energy (for if the temperature changes */
1211
1212             if (fep->edHdLPrintEnergy != edHdLPrintEnergyNO)
1213             {
1214                 switch (fep->edHdLPrintEnergy)
1215                 {
1216                     case edHdLPrintEnergyPOTENTIAL:
1217                         store_energy = enerd->term[F_EPOT];
1218                         break;
1219                     case edHdLPrintEnergyTOTAL:
1220                     case edHdLPrintEnergyYES:
1221                     default:
1222                         store_energy = enerd->term[F_ETOT];
1223                 }
1224                 fprintf(md->fp_dhdl, " %#.8g", store_energy);
1225             }
1226
1227             if (fep->dhdl_derivatives == edhdlderivativesYES)
1228             {
1229                 for (i = 0; i < efptNR; i++)
1230                 {
1231                     if (fep->separate_dvdl[i])
1232                     {
1233                         /* assumes F_DVDL is first */
1234                         fprintf(md->fp_dhdl, " %#.8g", enerd->term[F_DVDL+i]);
1235                     }
1236                 }
1237             }
1238             for (i = fep->lambda_start_n; i < fep->lambda_stop_n; i++)
1239             {
1240                 fprintf(md->fp_dhdl, " %#.8g", md->dE[i]);
1241             }
1242             if (md->bDynBox &&
1243                 md->bDiagPres &&
1244                 (md->epc != epcNO) &&
1245                 (enerd->n_lambda > 0) &&
1246                 (fep->init_lambda < 0))
1247             {
1248                 fprintf(md->fp_dhdl, " %#.8g", pv);  /* PV term only needed when
1249                                                         there are alternate state
1250                                                         lambda and we're not in
1251                                                         compatibility mode */
1252             }
1253             fprintf(md->fp_dhdl, "\n");
1254             /* and the binary free energy output */
1255         }
1256         if (md->dhc && bDoDHDL)
1257         {
1258             int idhdl = 0;
1259             for (i = 0; i < efptNR; i++)
1260             {
1261                 if (fep->separate_dvdl[i])
1262                 {
1263                     /* assumes F_DVDL is first */
1264                     store_dhdl[idhdl] = enerd->term[F_DVDL+i];
1265                     idhdl            += 1;
1266                 }
1267             }
1268             store_energy = enerd->term[F_ETOT];
1269             /* store_dh is dE */
1270             mde_delta_h_coll_add_dh(md->dhc,
1271                                     static_cast<double>(state->fep_state),
1272                                     store_energy,
1273                                     pv,
1274                                     store_dhdl,
1275                                     md->dE + fep->lambda_start_n,
1276                                     time);
1277         }
1278     }
1279 }
1280
1281 }   // namespace
1282
1283 void EnergyOutput::recordNonEnergyStep()
1284 {
1285     ebin_increase_count(mdebin->ebin, false);
1286 }
1287
1288 namespace
1289 {
1290
1291 //! Legacy output function
1292 void npr(FILE *log, int n, char c)
1293 {
1294     for (; (n > 0); n--)
1295     {
1296         fprintf(log, "%c", c);
1297     }
1298 }
1299
1300 //! Legacy output function
1301 void pprint(FILE *log, const char *s, t_mdebin *md)
1302 {
1303     char CHAR = '#';
1304     int  slen;
1305     char buf1[22], buf2[22];
1306
1307     slen = strlen(s);
1308     fprintf(log, "\t<======  ");
1309     npr(log, slen, CHAR);
1310     fprintf(log, "  ==>\n");
1311     fprintf(log, "\t<====  %s  ====>\n", s);
1312     fprintf(log, "\t<==  ");
1313     npr(log, slen, CHAR);
1314     fprintf(log, "  ======>\n\n");
1315
1316     fprintf(log, "\tStatistics over %s steps using %s frames\n",
1317             gmx_step_str(md->ebin->nsteps_sim, buf1),
1318             gmx_step_str(md->ebin->nsum_sim, buf2));
1319     fprintf(log, "\n");
1320 }
1321
1322 }   // namespace
1323
1324 void print_ebin_header(FILE *log, int64_t steps, double time)
1325 {
1326     char buf[22];
1327
1328     fprintf(log, "   %12s   %12s\n"
1329             "   %12s   %12.5f\n\n",
1330             "Step", "Time", gmx_step_str(steps, buf), time);
1331 }
1332
1333 namespace
1334 {
1335
1336 // TODO It is too many responsibilities for this function to handle
1337 // both .edr and .log output for both per-time and time-average data.
1338 //! Legacy ebin output function
1339 void print_ebin(ener_file_t fp_ene, gmx_bool bEne, gmx_bool bDR, gmx_bool bOR,
1340                 FILE *log,
1341                 int64_t step, double time,
1342                 int mode,
1343                 t_mdebin *md, t_fcdata *fcd,
1344                 SimulationGroups *groups, t_grpopts *opts,
1345                 gmx::Awh *awh)
1346 {
1347     /*static char **grpnms=NULL;*/
1348     char         buf[246];
1349     int          i, j, n, ni, nj, b;
1350     int          ndisre = 0;
1351
1352     /* these are for the old-style blocks (1 subblock, only reals), because
1353        there can be only one per ID for these */
1354     int          nr[enxNR];
1355     int          id[enxNR];
1356     real        *block[enxNR];
1357
1358     t_enxframe   fr;
1359
1360     if (mode == eprAVER && md->ebin->nsum_sim <= 0)
1361     {
1362         if (log)
1363         {
1364             fprintf(log, "Not enough data recorded to report energy averages\n");
1365         }
1366         return;
1367     }
1368
1369     switch (mode)
1370     {
1371         case eprNORMAL:
1372             init_enxframe(&fr);
1373             fr.t            = time;
1374             fr.step         = step;
1375             fr.nsteps       = md->ebin->nsteps;
1376             fr.dt           = md->delta_t;
1377             fr.nsum         = md->ebin->nsum;
1378             fr.nre          = (bEne) ? md->ebin->nener : 0;
1379             fr.ener         = md->ebin->e;
1380             ndisre          = bDR ? fcd->disres.npair : 0;
1381             /* Optional additional old-style (real-only) blocks. */
1382             for (i = 0; i < enxNR; i++)
1383             {
1384                 nr[i] = 0;
1385             }
1386             if (bOR && fcd->orires.nr > 0)
1387             {
1388                 diagonalize_orires_tensors(&(fcd->orires));
1389                 nr[enxOR]     = fcd->orires.nr;
1390                 block[enxOR]  = fcd->orires.otav;
1391                 id[enxOR]     = enxOR;
1392                 nr[enxORI]    = (fcd->orires.oinsl != fcd->orires.otav) ?
1393                     fcd->orires.nr : 0;
1394                 block[enxORI] = fcd->orires.oinsl;
1395                 id[enxORI]    = enxORI;
1396                 nr[enxORT]    = fcd->orires.nex*12;
1397                 block[enxORT] = fcd->orires.eig;
1398                 id[enxORT]    = enxORT;
1399             }
1400
1401             /* whether we are going to wrte anything out: */
1402             if (fr.nre || ndisre || nr[enxOR] || nr[enxORI])
1403             {
1404
1405                 /* the old-style blocks go first */
1406                 fr.nblock = 0;
1407                 for (i = 0; i < enxNR; i++)
1408                 {
1409                     if (nr[i] > 0)
1410                     {
1411                         fr.nblock = i + 1;
1412                     }
1413                 }
1414                 add_blocks_enxframe(&fr, fr.nblock);
1415                 for (b = 0; b < fr.nblock; b++)
1416                 {
1417                     add_subblocks_enxblock(&(fr.block[b]), 1);
1418                     fr.block[b].id        = id[b];
1419                     fr.block[b].sub[0].nr = nr[b];
1420 #if !GMX_DOUBLE
1421                     fr.block[b].sub[0].type = xdr_datatype_float;
1422                     fr.block[b].sub[0].fval = block[b];
1423 #else
1424                     fr.block[b].sub[0].type = xdr_datatype_double;
1425                     fr.block[b].sub[0].dval = block[b];
1426 #endif
1427                 }
1428
1429                 /* check for disre block & fill it. */
1430                 if (ndisre > 0)
1431                 {
1432                     int db = fr.nblock;
1433                     fr.nblock += 1;
1434                     add_blocks_enxframe(&fr, fr.nblock);
1435
1436                     add_subblocks_enxblock(&(fr.block[db]), 2);
1437                     fr.block[db].id        = enxDISRE;
1438                     fr.block[db].sub[0].nr = ndisre;
1439                     fr.block[db].sub[1].nr = ndisre;
1440 #if !GMX_DOUBLE
1441                     fr.block[db].sub[0].type = xdr_datatype_float;
1442                     fr.block[db].sub[1].type = xdr_datatype_float;
1443                     fr.block[db].sub[0].fval = fcd->disres.rt;
1444                     fr.block[db].sub[1].fval = fcd->disres.rm3tav;
1445 #else
1446                     fr.block[db].sub[0].type = xdr_datatype_double;
1447                     fr.block[db].sub[1].type = xdr_datatype_double;
1448                     fr.block[db].sub[0].dval = fcd->disres.rt;
1449                     fr.block[db].sub[1].dval = fcd->disres.rm3tav;
1450 #endif
1451                 }
1452                 /* here we can put new-style blocks */
1453
1454                 /* Free energy perturbation blocks */
1455                 if (md->dhc)
1456                 {
1457                     mde_delta_h_coll_handle_block(md->dhc, &fr, fr.nblock);
1458                 }
1459
1460                 /* we can now free & reset the data in the blocks */
1461                 if (md->dhc)
1462                 {
1463                     mde_delta_h_coll_reset(md->dhc);
1464                 }
1465
1466                 /* AWH bias blocks. */
1467                 if (awh != nullptr)  // TODO: add boolean in t_mdebin. See in mdebin.h.
1468                 {
1469                     awh->writeToEnergyFrame(step, &fr);
1470                 }
1471
1472                 /* do the actual I/O */
1473                 do_enx(fp_ene, &fr);
1474                 if (fr.nre)
1475                 {
1476                     /* We have stored the sums, so reset the sum history */
1477                     reset_ebin_sums(md->ebin);
1478                 }
1479             }
1480             free_enxframe(&fr);
1481             break;
1482         case eprAVER:
1483             if (log)
1484             {
1485                 pprint(log, "A V E R A G E S", md);
1486             }
1487             break;
1488         case eprRMS:
1489             if (log)
1490             {
1491                 pprint(log, "R M S - F L U C T U A T I O N S", md);
1492             }
1493             break;
1494         default:
1495             gmx_fatal(FARGS, "Invalid print mode (%d)", mode);
1496     }
1497
1498     if (log)
1499     {
1500         if (opts)
1501         {
1502             for (i = 0; i < opts->ngtc; i++)
1503             {
1504                 if (opts->annealing[i] != eannNO)
1505                 {
1506                     fprintf(log, "Current ref_t for group %s: %8.1f\n",
1507                             *(groups->groupNames[groups->groups[SimulationAtomGroupType::TemperatureCoupling].nm_ind[i]]),
1508                             opts->ref_t[i]);
1509                 }
1510             }
1511         }
1512         if (mode == eprNORMAL && bOR && fcd->orires.nr > 0)
1513         {
1514             print_orires_log(log, &(fcd->orires));
1515         }
1516         fprintf(log, "   Energies (%s)\n", unit_energy);
1517         pr_ebin(log, md->ebin, md->ie, md->f_nre+md->nCrmsd, 5, mode, TRUE);
1518         fprintf(log, "\n");
1519
1520         if (mode == eprAVER)
1521         {
1522             if (md->bDynBox)
1523             {
1524                 pr_ebin(log, md->ebin, md->ib, md->bTricl ? NTRICLBOXS : NBOXS, 5,
1525                         mode, TRUE);
1526                 fprintf(log, "\n");
1527             }
1528             if (md->bConstrVir)
1529             {
1530                 fprintf(log, "   Constraint Virial (%s)\n", unit_energy);
1531                 pr_ebin(log, md->ebin, md->isvir, 9, 3, mode, FALSE);
1532                 fprintf(log, "\n");
1533                 fprintf(log, "   Force Virial (%s)\n", unit_energy);
1534                 pr_ebin(log, md->ebin, md->ifvir, 9, 3, mode, FALSE);
1535                 fprintf(log, "\n");
1536             }
1537             if (md->bPres)
1538             {
1539                 fprintf(log, "   Total Virial (%s)\n", unit_energy);
1540                 pr_ebin(log, md->ebin, md->ivir, 9, 3, mode, FALSE);
1541                 fprintf(log, "\n");
1542                 fprintf(log, "   Pressure (%s)\n", unit_pres_bar);
1543                 pr_ebin(log, md->ebin, md->ipres, 9, 3, mode, FALSE);
1544                 fprintf(log, "\n");
1545             }
1546             if (md->bMu)
1547             {
1548                 fprintf(log, "   Total Dipole (%s)\n", unit_dipole_D);
1549                 pr_ebin(log, md->ebin, md->imu, 3, 3, mode, FALSE);
1550                 fprintf(log, "\n");
1551             }
1552
1553             if (md->nE > 1)
1554             {
1555                 if (md->print_grpnms == nullptr)
1556                 {
1557                     snew(md->print_grpnms, md->nE);
1558                     n = 0;
1559                     for (i = 0; (i < md->nEg); i++)
1560                     {
1561                         ni = groups->groups[SimulationAtomGroupType::EnergyOutput].nm_ind[i];
1562                         for (j = i; (j < md->nEg); j++)
1563                         {
1564                             nj = groups->groups[SimulationAtomGroupType::EnergyOutput].nm_ind[j];
1565                             sprintf(buf, "%s-%s", *(groups->groupNames[ni]),
1566                                     *(groups->groupNames[nj]));
1567                             md->print_grpnms[n++] = gmx_strdup(buf);
1568                         }
1569                     }
1570                 }
1571                 sprintf(buf, "Epot (%s)", unit_energy);
1572                 fprintf(log, "%15s   ", buf);
1573                 for (i = 0; (i < egNR); i++)
1574                 {
1575                     if (md->bEInd[i])
1576                     {
1577                         fprintf(log, "%12s   ", egrp_nm[i]);
1578                     }
1579                 }
1580                 fprintf(log, "\n");
1581                 for (i = 0; (i < md->nE); i++)
1582                 {
1583                     fprintf(log, "%15s", md->print_grpnms[i]);
1584                     pr_ebin(log, md->ebin, md->igrp[i], md->nEc, md->nEc, mode,
1585                             FALSE);
1586                 }
1587                 fprintf(log, "\n");
1588             }
1589             if (md->nTC > 1)
1590             {
1591                 pr_ebin(log, md->ebin, md->itemp, md->nTC, 4, mode, TRUE);
1592                 fprintf(log, "\n");
1593             }
1594             if (md->nU > 1)
1595             {
1596                 fprintf(log, "%15s   %12s   %12s   %12s\n",
1597                         "Group", "Ux", "Uy", "Uz");
1598                 for (i = 0; (i < md->nU); i++)
1599                 {
1600                     ni = groups->groups[SimulationAtomGroupType::Acceleration].nm_ind[i];
1601                     fprintf(log, "%15s", *groups->groupNames[ni]);
1602                     pr_ebin(log, md->ebin, md->iu+3*i, 3, 3, mode, FALSE);
1603                 }
1604                 fprintf(log, "\n");
1605             }
1606         }
1607     }
1608
1609 }
1610
1611 //! Legacy update function
1612 void update_energyhistory(energyhistory_t * enerhist, const t_mdebin * mdebin)
1613 {
1614     const t_ebin * const ebin = mdebin->ebin;
1615
1616     enerhist->nsteps     = ebin->nsteps;
1617     enerhist->nsum       = ebin->nsum;
1618     enerhist->nsteps_sim = ebin->nsteps_sim;
1619     enerhist->nsum_sim   = ebin->nsum_sim;
1620
1621     if (ebin->nsum > 0)
1622     {
1623         /* This will only actually resize the first time */
1624         enerhist->ener_ave.resize(ebin->nener);
1625         enerhist->ener_sum.resize(ebin->nener);
1626
1627         for (int i = 0; i < ebin->nener; i++)
1628         {
1629             enerhist->ener_ave[i] = ebin->e[i].eav;
1630             enerhist->ener_sum[i] = ebin->e[i].esum;
1631         }
1632     }
1633
1634     if (ebin->nsum_sim > 0)
1635     {
1636         /* This will only actually resize the first time */
1637         enerhist->ener_sum_sim.resize(ebin->nener);
1638
1639         for (int i = 0; i < ebin->nener; i++)
1640         {
1641             enerhist->ener_sum_sim[i] = ebin->e_sim[i].esum;
1642         }
1643     }
1644     if (mdebin->dhc)
1645     {
1646         mde_delta_h_coll_update_energyhistory(mdebin->dhc, enerhist);
1647     }
1648 }
1649
1650 //! Legacy restore function
1651 void restore_energyhistory_from_state(t_mdebin              * mdebin,
1652                                       const energyhistory_t * enerhist)
1653 {
1654     unsigned int nener = static_cast<unsigned int>(mdebin->ebin->nener);
1655
1656     GMX_RELEASE_ASSERT(enerhist, "Need valid history to restore");
1657
1658     if ((enerhist->nsum     > 0 && nener != enerhist->ener_sum.size()) ||
1659         (enerhist->nsum_sim > 0 && nener != enerhist->ener_sum_sim.size()))
1660     {
1661         gmx_fatal(FARGS, "Mismatch between number of energies in run input (%u) and checkpoint file (%zu or %zu).",
1662                   nener, enerhist->ener_sum.size(), enerhist->ener_sum_sim.size());
1663     }
1664
1665     mdebin->ebin->nsteps     = enerhist->nsteps;
1666     mdebin->ebin->nsum       = enerhist->nsum;
1667     mdebin->ebin->nsteps_sim = enerhist->nsteps_sim;
1668     mdebin->ebin->nsum_sim   = enerhist->nsum_sim;
1669
1670     for (int i = 0; i < mdebin->ebin->nener; i++)
1671     {
1672         mdebin->ebin->e[i].eav  =
1673             (enerhist->nsum > 0 ? enerhist->ener_ave[i] : 0);
1674         mdebin->ebin->e[i].esum =
1675             (enerhist->nsum > 0 ? enerhist->ener_sum[i] : 0);
1676         mdebin->ebin->e_sim[i].esum =
1677             (enerhist->nsum_sim > 0 ? enerhist->ener_sum_sim[i] : 0);
1678     }
1679     if (mdebin->dhc)
1680     {
1681         mde_delta_h_coll_restore_energyhistory(mdebin->dhc, enerhist->deltaHForeignLambdas.get());
1682     }
1683 }
1684
1685 }   // namespace
1686
1687 EnergyOutput::EnergyOutput()
1688     : mdebin(nullptr)
1689 {
1690 }
1691
1692 void EnergyOutput::prepare(ener_file        *fp_ene,
1693                            const gmx_mtop_t *mtop,
1694                            const t_inputrec *ir,
1695                            const pull_t     *pull_work,
1696                            FILE             *fp_dhdl,
1697                            bool              isRerun)
1698 {
1699     mdebin = init_mdebin(fp_ene, mtop, ir, pull_work, fp_dhdl, isRerun);
1700 }
1701
1702 EnergyOutput::~EnergyOutput()
1703 {
1704     done_mdebin(mdebin);
1705 }
1706
1707 t_ebin *EnergyOutput::getEbin()
1708 {
1709     return mdebin->ebin;
1710 }
1711
1712 void EnergyOutput::addDataAtEnergyStep(bool                    bDoDHDL,
1713                                        bool                    bSum,
1714                                        double                  time,
1715                                        real                    tmass,
1716                                        gmx_enerdata_t         *enerd,
1717                                        t_state                *state,
1718                                        t_lambda               *fep,
1719                                        t_expanded             *expand,
1720                                        matrix                  box,
1721                                        tensor                  svir,
1722                                        tensor                  fvir,
1723                                        tensor                  vir,
1724                                        tensor                  pres,
1725                                        gmx_ekindata_t         *ekind,
1726                                        rvec                    mu_tot,
1727                                        const gmx::Constraints *constr)
1728 {
1729     upd_mdebin(mdebin, bDoDHDL, bSum, time, tmass, enerd, state, fep,
1730                expand, box, svir, fvir, vir, pres, ekind, mu_tot, constr);
1731 }
1732
1733 void EnergyOutput::printStepToEnergyFile(ener_file *fp_ene, bool bEne, bool bDR, bool bOR,
1734                                          FILE *log,
1735                                          int64_t step, double time,
1736                                          int mode,
1737                                          t_fcdata *fcd,
1738                                          SimulationGroups *groups, t_grpopts *opts,
1739                                          gmx::Awh *awh)
1740 {
1741     print_ebin(fp_ene, bEne, bDR, bOR, log, step, time, mode,
1742                mdebin, fcd, groups, opts, awh);
1743 }
1744
1745 int EnergyOutput::numEnergyTerms() const
1746 {
1747     return mdebin->ebin->nener;
1748 }
1749
1750 void EnergyOutput::fillEnergyHistory(energyhistory_t *enerhist) const
1751 {
1752     update_energyhistory(enerhist, mdebin);
1753 }
1754
1755 void EnergyOutput::restoreFromEnergyHistory(const energyhistory_t &enerhist)
1756 {
1757     restore_energyhistory_from_state(mdebin, &enerhist);
1758 }
1759
1760 } // namespace gmx