Adding energy output field for density fitting
[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 /*! \internal \file
38  * \brief Defines code that writes energy-like quantities.
39  *
40  * \author Mark Abraham <mark.j.abraham@gmail.com>
41  * \author Paul Bauer <paul.bauer.q@gmail.com>
42  * \author Artem Zhmurov <zhmurov@gmail.com>
43  *
44  * \ingroup module_mdlib
45  */
46 #include "gmxpre.h"
47
48 #include "energyoutput.h"
49
50 #include <cfloat>
51 #include <cstdlib>
52 #include <cstring>
53
54 #include <array>
55 #include <string>
56
57 #include "gromacs/awh/awh.h"
58 #include "gromacs/fileio/enxio.h"
59 #include "gromacs/fileio/gmxfio.h"
60 #include "gromacs/fileio/xvgr.h"
61 #include "gromacs/gmxlib/network.h"
62 #include "gromacs/listed_forces/disre.h"
63 #include "gromacs/listed_forces/orires.h"
64 #include "gromacs/math/functions.h"
65 #include "gromacs/math/units.h"
66 #include "gromacs/math/vec.h"
67 #include "gromacs/mdlib/constr.h"
68 #include "gromacs/mdlib/ebin.h"
69 #include "gromacs/mdlib/mdebin_bar.h"
70 #include "gromacs/mdtypes/energyhistory.h"
71 #include "gromacs/mdtypes/fcdata.h"
72 #include "gromacs/mdtypes/group.h"
73 #include "gromacs/mdtypes/inputrec.h"
74 #include "gromacs/mdtypes/md_enums.h"
75 #include "gromacs/mdtypes/state.h"
76 #include "gromacs/pbcutil/pbc.h"
77 #include "gromacs/pulling/pull.h"
78 #include "gromacs/topology/mtop_util.h"
79 #include "gromacs/trajectory/energyframe.h"
80 #include "gromacs/utility/arraysize.h"
81 #include "gromacs/utility/fatalerror.h"
82 #include "gromacs/utility/mdmodulenotification.h"
83 #include "gromacs/utility/smalloc.h"
84 #include "gromacs/utility/stringutil.h"
85
86 //! Labels for energy file quantities
87 //! \{
88 static const char                 *conrmsd_nm[] = { "Constr. rmsd", "Constr.2 rmsd" };
89
90 static std::array<const char *, 3> boxs_nm = { "Box-X", "Box-Y", "Box-Z" };
91
92 static std::array<const char *, 6> tricl_boxs_nm = {
93     "Box-XX", "Box-YY", "Box-ZZ",
94     "Box-YX", "Box-ZX", "Box-ZY"
95 };
96
97 static const char                 *vol_nm[] = { "Volume" };
98
99 static const char                 *dens_nm[] = {"Density" };
100
101 static const char                 *pv_nm[] = {"pV" };
102
103 static const char                 *enthalpy_nm[] = {"Enthalpy" };
104
105 static std::array<const char *, 6> boxvel_nm = {
106     "Box-Vel-XX", "Box-Vel-YY", "Box-Vel-ZZ",
107     "Box-Vel-YX", "Box-Vel-ZX", "Box-Vel-ZY"
108 };
109
110 const char *egrp_nm[egNR+1] = {
111     "Coul-SR", "LJ-SR", "Buck-SR",
112     "Coul-14", "LJ-14", nullptr
113 };
114 //! \}
115
116 namespace gmx
117 {
118
119 /*! \brief Energy output class
120  *
121  * This is the collection of energy averages collected during mdrun, and to
122  * be written out to the .edr file.
123  *
124  * \todo Use more std containers.
125  * \todo Remove GMX_CONSTRAINTVIR
126  * \todo Write free-energy output also to energy file (after adding more tests)
127  */
128 EnergyOutput::EnergyOutput(ener_file *              fp_ene,
129                            const gmx_mtop_t *       mtop,
130                            const t_inputrec *       ir,
131                            const pull_t *           pull_work,
132                            FILE *                   fp_dhdl,
133                            bool                     isRerun,
134                            const MdModulesNotifier &mdModulesNotifier)
135 {
136     const char                *ener_nm[F_NRE];
137     static const char         *vir_nm[] = {
138         "Vir-XX", "Vir-XY", "Vir-XZ",
139         "Vir-YX", "Vir-YY", "Vir-YZ",
140         "Vir-ZX", "Vir-ZY", "Vir-ZZ"
141     };
142     static const char         *sv_nm[] = {
143         "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ",
144         "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ",
145         "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ"
146     };
147     static const char         *fv_nm[] = {
148         "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ",
149         "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ",
150         "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ"
151     };
152     static const char         *pres_nm[] = {
153         "Pres-XX", "Pres-XY", "Pres-XZ",
154         "Pres-YX", "Pres-YY", "Pres-YZ",
155         "Pres-ZX", "Pres-ZY", "Pres-ZZ"
156     };
157     static const char         *surft_nm[] = {
158         "#Surf*SurfTen"
159     };
160     static const char         *mu_nm[] = {
161         "Mu-X", "Mu-Y", "Mu-Z"
162     };
163     static const char         *vcos_nm[] = {
164         "2CosZ*Vel-X"
165     };
166     static const char         *visc_nm[] = {
167         "1/Viscosity"
168     };
169     static const char         *baro_nm[] = {
170         "Barostat"
171     };
172
173     const SimulationGroups    *groups;
174     char                     **gnm;
175     char                       buf[256];
176     const char                *bufi;
177     int                        i, j, ni, nj, n, k, kk, ncon, nset;
178     bool                       bBHAM, b14;
179
180     if (EI_DYNAMICS(ir->eI))
181     {
182         delta_t_ = ir->delta_t;
183     }
184     else
185     {
186         delta_t_ = 0;
187     }
188
189     groups = &mtop->groups;
190
191     bBHAM = (mtop->ffparams.numTypes() > 0) && (mtop->ffparams.functype[0] == F_BHAM);
192     b14   = (gmx_mtop_ftype_count(mtop, F_LJ14) > 0 ||
193              gmx_mtop_ftype_count(mtop, F_LJC14_Q) > 0);
194
195     ncon           = gmx_mtop_ftype_count(mtop, F_CONSTR);
196     nset           = gmx_mtop_ftype_count(mtop, F_SETTLE);
197     bool bConstr   = (ncon > 0 || nset > 0) && !isRerun;
198     bConstrVir_ = false;
199     nCrmsd_     = 0;
200     if (bConstr)
201     {
202         if (ncon > 0 && ir->eConstrAlg == econtLINCS)
203         {
204             nCrmsd_ = 1;
205         }
206         bConstrVir_ = (getenv("GMX_CONSTRAINTVIR") != nullptr);
207     }
208     else
209     {
210         nCrmsd_ = 0;
211     }
212
213     /* Energy monitoring */
214     for (i = 0; i < egNR; i++)
215     {
216         bEInd_[i] = false;
217     }
218
219     // Setting true only to those energy terms, that have active interactions and
220     // are not vsite terms (not VSITE2, VSITE3, VSITE3FD, VSITE3FAD, VSITE3OUT, VSITE4FD, VSITE4FDN, or VSITEN)
221     for (i = 0; i < F_NRE; i++)
222     {
223         bEner_[i] = (gmx_mtop_ftype_count(mtop, i) > 0) &&
224             ((interaction_function[i].flags & IF_VSITE) == 0);
225     }
226
227     if (!isRerun)
228     {
229         bEner_[F_EKIN]           = EI_DYNAMICS(ir->eI);
230         bEner_[F_ETOT]           = EI_DYNAMICS(ir->eI);
231         bEner_[F_TEMP]           = EI_DYNAMICS(ir->eI);
232
233         bEner_[F_ECONSERVED]     = integratorHasConservedEnergyQuantity(ir);
234         bEner_[F_PDISPCORR]      = (ir->eDispCorr != edispcNO);
235         bEner_[F_PRES]           = true;
236     }
237
238     bEner_[F_LJ]             = !bBHAM;
239     bEner_[F_BHAM]           = bBHAM;
240     bEner_[F_EQM]            = ir->bQMMM;
241     bEner_[F_RF_EXCL]        = (EEL_RF(ir->coulombtype) && ir->cutoff_scheme == ecutsGROUP);
242     bEner_[F_COUL_RECIP]     = EEL_FULL(ir->coulombtype);
243     bEner_[F_LJ_RECIP]       = EVDW_PME(ir->vdwtype);
244     bEner_[F_LJ14]           = b14;
245     bEner_[F_COUL14]         = b14;
246     bEner_[F_LJC14_Q]        = false;
247     bEner_[F_LJC_PAIRS_NB]   = false;
248
249
250     bEner_[F_DVDL_COUL]      = (ir->efep != efepNO) && ir->fepvals->separate_dvdl[efptCOUL];
251     bEner_[F_DVDL_VDW]       = (ir->efep != efepNO) && ir->fepvals->separate_dvdl[efptVDW];
252     bEner_[F_DVDL_BONDED]    = (ir->efep != efepNO) && ir->fepvals->separate_dvdl[efptBONDED];
253     bEner_[F_DVDL_RESTRAINT] = (ir->efep != efepNO) && ir->fepvals->separate_dvdl[efptRESTRAINT];
254     bEner_[F_DKDL]           = (ir->efep != efepNO) && ir->fepvals->separate_dvdl[efptMASS];
255     bEner_[F_DVDL]           = (ir->efep != efepNO) && ir->fepvals->separate_dvdl[efptFEP];
256
257     bEner_[F_CONSTR]         = false;
258     bEner_[F_CONSTRNC]       = false;
259     bEner_[F_SETTLE]         = false;
260
261     bEner_[F_COUL_SR]        = true;
262     bEner_[F_EPOT]           = true;
263
264     bEner_[F_DISPCORR]       = (ir->eDispCorr != edispcNO);
265     bEner_[F_DISRESVIOL]     = (gmx_mtop_ftype_count(mtop, F_DISRES) > 0);
266     bEner_[F_ORIRESDEV]      = (gmx_mtop_ftype_count(mtop, F_ORIRES) > 0);
267     bEner_[F_COM_PULL]       = ((ir->bPull && pull_have_potential(pull_work)) || ir->bRot);
268
269     MdModulesEnergyOutputToDensityFittingRequestChecker mdModulesAddOutputToDensityFittingFieldRequest;
270     mdModulesNotifier.notifier_.notify(&mdModulesAddOutputToDensityFittingFieldRequest);
271
272     bEner_[F_DENSITYFITTING] = mdModulesAddOutputToDensityFittingFieldRequest.energyOutputToDensityFitting_;
273
274
275     // Counting the energy terms that will be printed and saving their names
276     f_nre_ = 0;
277     for (i = 0; i < F_NRE; i++)
278     {
279         if (bEner_[i])
280         {
281             ener_nm[f_nre_] = interaction_function[i].longname;
282             f_nre_++;
283         }
284     }
285
286     epc_            = isRerun ? epcNO : ir->epc;
287     bDiagPres_      = !TRICLINIC(ir->ref_p) && !isRerun;
288     ref_p_          = (ir->ref_p[XX][XX]+ir->ref_p[YY][YY]+ir->ref_p[ZZ][ZZ])/DIM;
289     bTricl_         = TRICLINIC(ir->compress) || TRICLINIC(ir->deform);
290     bDynBox_        = inputrecDynamicBox(ir);
291     etc_            = isRerun ? etcNO : ir->etc;
292     bNHC_trotter_   = inputrecNvtTrotter(ir) && !isRerun;
293     bPrintNHChains_ = ir->bPrintNHChains && !isRerun;
294     bMTTK_          = (inputrecNptTrotter(ir) || inputrecNphTrotter(ir)) && !isRerun;
295     bMu_            = inputrecNeedMutot(ir);
296     bPres_          = !isRerun;
297
298     ebin_  = mk_ebin();
299     /* Pass NULL for unit to let get_ebin_space determine the units
300      * for interaction_function[i].longname
301      */
302     ie_    = get_ebin_space(ebin_, f_nre_, ener_nm, nullptr);
303     if (nCrmsd_)
304     {
305         /* This should be called directly after the call for ie_,
306          * such that iconrmsd_ follows directly in the list.
307          */
308         iconrmsd_ = get_ebin_space(ebin_, nCrmsd_, conrmsd_nm, "");
309     }
310     if (bDynBox_)
311     {
312         ib_    = get_ebin_space(ebin_,
313                                 bTricl_ ? tricl_boxs_nm.size() : boxs_nm.size(),
314                                 bTricl_ ? tricl_boxs_nm.data() : boxs_nm.data(),
315                                 unit_length);
316         ivol_  = get_ebin_space(ebin_, 1, vol_nm,  unit_volume);
317         idens_ = get_ebin_space(ebin_, 1, dens_nm, unit_density_SI);
318         if (bDiagPres_)
319         {
320             ipv_       = get_ebin_space(ebin_, 1, pv_nm,   unit_energy);
321             ienthalpy_ = get_ebin_space(ebin_, 1, enthalpy_nm,   unit_energy);
322         }
323     }
324     if (bConstrVir_)
325     {
326         isvir_ = get_ebin_space(ebin_, asize(sv_nm), sv_nm, unit_energy);
327         ifvir_ = get_ebin_space(ebin_, asize(fv_nm), fv_nm, unit_energy);
328     }
329     if (bPres_)
330     {
331         ivir_   = get_ebin_space(ebin_, asize(vir_nm), vir_nm, unit_energy);
332         ipres_  = get_ebin_space(ebin_, asize(pres_nm), pres_nm, unit_pres_bar);
333         isurft_ = get_ebin_space(ebin_, asize(surft_nm), surft_nm,
334                                  unit_surft_bar);
335     }
336     if (epc_ == epcPARRINELLORAHMAN || epc_ == epcMTTK)
337     {
338         ipc_ = get_ebin_space(ebin_, bTricl_ ? boxvel_nm.size() : DIM,
339                               boxvel_nm.data(), unit_vel);
340     }
341     if (bMu_)
342     {
343         imu_    = get_ebin_space(ebin_, asize(mu_nm), mu_nm, unit_dipole_D);
344     }
345     if (ir->cos_accel != 0)
346     {
347         ivcos_ = get_ebin_space(ebin_, asize(vcos_nm), vcos_nm, unit_vel);
348         ivisc_ = get_ebin_space(ebin_, asize(visc_nm), visc_nm,
349                                 unit_invvisc_SI);
350     }
351
352     /* Energy monitoring */
353     for (i = 0; i < egNR; i++)
354     {
355         bEInd_[i] = false;
356     }
357     bEInd_[egCOULSR] = true;
358     bEInd_[egLJSR  ] = true;
359
360     if (bBHAM)
361     {
362         bEInd_[egLJSR]   = false;
363         bEInd_[egBHAMSR] = true;
364     }
365     if (b14)
366     {
367         bEInd_[egLJ14]   = true;
368         bEInd_[egCOUL14] = true;
369     }
370     nEc_ = 0;
371     for (i = 0; (i < egNR); i++)
372     {
373         if (bEInd_[i])
374         {
375             nEc_++;
376         }
377     }
378     n         = groups->groups[SimulationAtomGroupType::EnergyOutput].size();
379     nEg_      = n;
380     nE_       = (n*(n+1))/2;
381
382     snew(igrp_, nE_);
383     if (nE_ > 1)
384     {
385         n = 0;
386         snew(gnm, nEc_);
387         for (k = 0; (k < nEc_); k++)
388         {
389             snew(gnm[k], STRLEN);
390         }
391         for (i = 0; (i < gmx::ssize(groups->groups[SimulationAtomGroupType::EnergyOutput])); i++)
392         {
393             ni = groups->groups[SimulationAtomGroupType::EnergyOutput][i];
394             for (j = i; (j < gmx::ssize(groups->groups[SimulationAtomGroupType::EnergyOutput])); j++)
395             {
396                 nj = groups->groups[SimulationAtomGroupType::EnergyOutput][j];
397                 for (k = kk = 0; (k < egNR); k++)
398                 {
399                     if (bEInd_[k])
400                     {
401                         sprintf(gnm[kk], "%s:%s-%s", egrp_nm[k],
402                                 *(groups->groupNames[ni]), *(groups->groupNames[nj]));
403                         kk++;
404                     }
405                 }
406                 igrp_[n] = get_ebin_space(ebin_, nEc_,
407                                           gnm, unit_energy);
408                 n++;
409             }
410         }
411         for (k = 0; (k < nEc_); k++)
412         {
413             sfree(gnm[k]);
414         }
415         sfree(gnm);
416
417         if (n != nE_)
418         {
419             gmx_incons("Number of energy terms wrong");
420         }
421     }
422
423     nTC_  = isRerun ? 0 : groups->groups[SimulationAtomGroupType::TemperatureCoupling].size();
424     nNHC_ = ir->opts.nhchainlength; /* shorthand for number of NH chains */
425     if (bMTTK_)
426     {
427         nTCP_ = 1;  /* assume only one possible coupling system for barostat
428                             for now */
429     }
430     else
431     {
432         nTCP_ = 0;
433     }
434     if (etc_ == etcNOSEHOOVER)
435     {
436         if (bNHC_trotter_)
437         {
438             mde_n_ = 2*nNHC_*nTC_;
439         }
440         else
441         {
442             mde_n_ = 2*nTC_;
443         }
444         if (epc_ == epcMTTK)
445         {
446             mdeb_n_ = 2*nNHC_*nTCP_;
447         }
448     }
449     else
450     {
451         mde_n_  = nTC_;
452         mdeb_n_ = 0;
453     }
454
455     snew(tmp_r_, mde_n_);
456     // TODO redo the group name memory management to make it more clear
457     char **grpnms;
458     snew(grpnms, std::max(mde_n_, mdeb_n_)); // Just in case mdeb_n_ > mde_n_
459
460     for (i = 0; (i < nTC_); i++)
461     {
462         ni = groups->groups[SimulationAtomGroupType::TemperatureCoupling][i];
463         sprintf(buf, "T-%s", *(groups->groupNames[ni]));
464         grpnms[i] = gmx_strdup(buf);
465     }
466     itemp_ = get_ebin_space(ebin_, nTC_, grpnms,
467                             unit_temp_K);
468     for (i = 0; i < nTC_; i++)
469     {
470         sfree(grpnms[i]);
471     }
472
473     int allocated = 0;
474     if (etc_ == etcNOSEHOOVER)
475     {
476         if (bPrintNHChains_)
477         {
478             if (bNHC_trotter_)
479             {
480                 for (i = 0; (i < nTC_); i++)
481                 {
482                     ni   = groups->groups[SimulationAtomGroupType::TemperatureCoupling][i];
483                     bufi = *(groups->groupNames[ni]);
484                     for (j = 0; (j < nNHC_); j++)
485                     {
486                         sprintf(buf, "Xi-%d-%s", j, bufi);
487                         grpnms[2*(i*nNHC_+j)] = gmx_strdup(buf);
488                         sprintf(buf, "vXi-%d-%s", j, bufi);
489                         grpnms[2*(i*nNHC_+j)+1] = gmx_strdup(buf);
490                     }
491                 }
492                 itc_ = get_ebin_space(ebin_, mde_n_,
493                                       grpnms, unit_invtime);
494                 allocated = mde_n_;
495                 if (bMTTK_)
496                 {
497                     for (i = 0; (i < nTCP_); i++)
498                     {
499                         bufi = baro_nm[0];  /* All barostat DOF's together for now. */
500                         for (j = 0; (j < nNHC_); j++)
501                         {
502                             sprintf(buf, "Xi-%d-%s", j, bufi);
503                             grpnms[2*(i*nNHC_+j)] = gmx_strdup(buf);
504                             sprintf(buf, "vXi-%d-%s", j, bufi);
505                             grpnms[2*(i*nNHC_+j)+1] = gmx_strdup(buf);
506                         }
507                     }
508                     itcb_ = get_ebin_space(ebin_, mdeb_n_,
509                                            grpnms, unit_invtime);
510                     allocated = mdeb_n_;
511                 }
512             }
513             else
514             {
515                 for (i = 0; (i < nTC_); i++)
516                 {
517                     ni   = groups->groups[SimulationAtomGroupType::TemperatureCoupling][i];
518                     bufi = *(groups->groupNames[ni]);
519                     sprintf(buf, "Xi-%s", bufi);
520                     grpnms[2*i] = gmx_strdup(buf);
521                     sprintf(buf, "vXi-%s", bufi);
522                     grpnms[2*i+1] = gmx_strdup(buf);
523                 }
524                 itc_ = get_ebin_space(ebin_, mde_n_,
525                                       grpnms, unit_invtime);
526                 allocated = mde_n_;
527             }
528         }
529     }
530     else if (etc_ == etcBERENDSEN || etc_ == etcYES ||
531              etc_ == etcVRESCALE)
532     {
533         for (i = 0; (i < nTC_); i++)
534         {
535             ni = groups->groups[SimulationAtomGroupType::TemperatureCoupling][i];
536             sprintf(buf, "Lamb-%s", *(groups->groupNames[ni]));
537             grpnms[i] = gmx_strdup(buf);
538         }
539         itc_        = get_ebin_space(ebin_, mde_n_, grpnms, "");
540         allocated   = mde_n_;
541     }
542
543     for (i = 0; i < allocated; i++)
544     {
545         sfree(grpnms[i]);
546     }
547     sfree(grpnms);
548
549     nU_ = groups->groups[SimulationAtomGroupType::Acceleration].size();
550     snew(tmp_v_, nU_);
551     if (nU_ > 1)
552     {
553         snew(grpnms, 3*nU_);
554         for (i = 0; (i < nU_); i++)
555         {
556             ni = groups->groups[SimulationAtomGroupType::Acceleration][i];
557             sprintf(buf, "Ux-%s", *(groups->groupNames[ni]));
558             grpnms[3*i+XX] = gmx_strdup(buf);
559             sprintf(buf, "Uy-%s", *(groups->groupNames[ni]));
560             grpnms[3*i+YY] = gmx_strdup(buf);
561             sprintf(buf, "Uz-%s", *(groups->groupNames[ni]));
562             grpnms[3*i+ZZ] = gmx_strdup(buf);
563         }
564         iu_ = get_ebin_space(ebin_, 3*nU_, grpnms, unit_vel);
565         for (i = 0; i < 3*nU_; i++)
566         {
567             sfree(grpnms[i]);
568         }
569         sfree(grpnms);
570     }
571
572     if (fp_ene)
573     {
574         do_enxnms(fp_ene, &ebin_->nener, &ebin_->enm);
575     }
576
577     /* check whether we're going to write dh histograms */
578     dhc_ = nullptr;
579     if (ir->fepvals->separate_dhdl_file == esepdhdlfileNO)
580     {
581         /* Currently dh histograms are only written with dynamics */
582         if (EI_DYNAMICS(ir->eI))
583         {
584             snew(dhc_, 1);
585
586             mde_delta_h_coll_init(dhc_, ir);
587         }
588         fp_dhdl_ = nullptr;
589         snew(dE_, ir->fepvals->n_lambda);
590     }
591     else
592     {
593         fp_dhdl_ = fp_dhdl;
594         snew(dE_, ir->fepvals->n_lambda);
595     }
596     if (ir->bSimTemp)
597     {
598         int i;
599         snew(temperatures_, ir->fepvals->n_lambda);
600         numTemperatures_ = ir->fepvals->n_lambda;
601         for (i = 0; i < ir->fepvals->n_lambda; i++)
602         {
603             temperatures_[i] = ir->simtempvals->temperatures[i];
604         }
605     }
606     else
607     {
608         numTemperatures_ = 0;
609     }
610
611 }
612
613 EnergyOutput::~EnergyOutput()
614 {
615     sfree(igrp_);
616     sfree(tmp_r_);
617     sfree(tmp_v_);
618     done_ebin(ebin_);
619     done_mde_delta_h_coll(dhc_);
620     sfree(dE_);
621     if (numTemperatures_ > 0)
622     {
623         sfree(temperatures_);
624     }
625 }
626
627 } // namespace gmx
628
629 /*! \brief Print a lambda vector to a string
630  *
631  * \param[in] fep                The inputrec's FEP input data
632  * \param[in] i                  The index of the lambda vector
633  * \param[in] get_native_lambda  Whether to print the native lambda
634  * \param[in] get_names          Whether to print the names rather than the values
635  * \param[in,out] str            The pre-allocated string buffer to print to.
636  */
637 static void print_lambda_vector(t_lambda *fep, int i,
638                                 bool get_native_lambda, bool get_names,
639                                 char *str)
640 {
641     int    j, k = 0;
642     int    Nsep = 0;
643
644     for (j = 0; j < efptNR; j++)
645     {
646         if (fep->separate_dvdl[j])
647         {
648             Nsep++;
649         }
650     }
651     str[0] = 0; /* reset the string */
652     if (Nsep > 1)
653     {
654         str += sprintf(str, "("); /* set the opening parenthesis*/
655     }
656     for (j = 0; j < efptNR; j++)
657     {
658         if (fep->separate_dvdl[j])
659         {
660             if (!get_names)
661             {
662                 if (get_native_lambda && fep->init_lambda >= 0)
663                 {
664                     str += sprintf(str, "%.4f", fep->init_lambda);
665                 }
666                 else
667                 {
668                     str += sprintf(str, "%.4f", fep->all_lambda[j][i]);
669                 }
670             }
671             else
672             {
673                 str += sprintf(str, "%s", efpt_singular_names[j]);
674             }
675             /* print comma for the next item */
676             if (k < Nsep-1)
677             {
678                 str += sprintf(str, ", ");
679             }
680             k++;
681         }
682     }
683     if (Nsep > 1)
684     {
685         /* and add the closing parenthesis */
686         sprintf(str, ")");
687     }
688 }
689
690 FILE *open_dhdl(const char *filename, const t_inputrec *ir,
691                 const gmx_output_env_t *oenv)
692 {
693     FILE       *fp;
694     const char *dhdl = "dH/d\\lambda", *deltag = "\\DeltaH", *lambda = "\\lambda",
695     *lambdastate     = "\\lambda state";
696     int         i, nsets, nsets_de, nsetsbegin;
697     int         n_lambda_terms = 0;
698     t_lambda   *fep            = ir->fepvals; /* for simplicity */
699     t_expanded *expand         = ir->expandedvals;
700     char        lambda_vec_str[STRLEN], lambda_name_str[STRLEN];
701
702     int         nsets_dhdl = 0;
703     int         s          = 0;
704     int         nsetsextend;
705     bool        write_pV = false;
706
707     /* count the number of different lambda terms */
708     for (i = 0; i < efptNR; i++)
709     {
710         if (fep->separate_dvdl[i])
711         {
712             n_lambda_terms++;
713         }
714     }
715
716     std::string title, label_x, label_y;
717     if (fep->n_lambda == 0)
718     {
719         title   = gmx::formatString("%s", dhdl);
720         label_x = gmx::formatString("Time (ps)");
721         label_y = gmx::formatString("%s (%s %s)",
722                                     dhdl, unit_energy, "[\\lambda]\\S-1\\N");
723     }
724     else
725     {
726         title   = gmx::formatString("%s and %s", dhdl, deltag);
727         label_x = gmx::formatString("Time (ps)");
728         label_y = gmx::formatString("%s and %s (%s %s)",
729                                     dhdl, deltag, unit_energy, "[\\8l\\4]\\S-1\\N");
730     }
731     fp = gmx_fio_fopen(filename, "w+");
732     xvgr_header(fp, title.c_str(), label_x, label_y, exvggtXNY, oenv);
733
734     std::string buf;
735     if (!(ir->bSimTemp))
736     {
737         buf = gmx::formatString("T = %g (K) ", ir->opts.ref_t[0]);
738     }
739     if ((ir->efep != efepSLOWGROWTH) && (ir->efep != efepEXPANDED))
740     {
741         if ( (fep->init_lambda >= 0)  && (n_lambda_terms == 1 ))
742         {
743             /* compatibility output */
744             buf += gmx::formatString("%s = %.4f", lambda, fep->init_lambda);
745         }
746         else
747         {
748             print_lambda_vector(fep, fep->init_fep_state, true, false,
749                                 lambda_vec_str);
750             print_lambda_vector(fep, fep->init_fep_state, true, true,
751                                 lambda_name_str);
752             buf += gmx::formatString("%s %d: %s = %s",
753                                      lambdastate, fep->init_fep_state,
754                                      lambda_name_str, lambda_vec_str);
755         }
756     }
757     xvgr_subtitle(fp, buf.c_str(), oenv);
758
759
760     nsets_dhdl = 0;
761     if (fep->dhdl_derivatives == edhdlderivativesYES)
762     {
763         nsets_dhdl = n_lambda_terms;
764     }
765     /* count the number of delta_g states */
766     nsets_de = fep->lambda_stop_n - fep->lambda_start_n;
767
768     nsets = nsets_dhdl + nsets_de; /* dhdl + fep differences */
769
770     if (fep->n_lambda > 0 && (expand->elmcmove > elmcmoveNO))
771     {
772         nsets += 1;   /*add fep state for expanded ensemble */
773     }
774
775     if (fep->edHdLPrintEnergy != edHdLPrintEnergyNO)
776     {
777         nsets += 1;  /* add energy to the dhdl as well */
778     }
779
780     nsetsextend = nsets;
781     if ((ir->epc != epcNO) && (fep->n_lambda > 0) && (fep->init_lambda < 0))
782     {
783         nsetsextend += 1; /* for PV term, other terms possible if required for
784                              the reduced potential (only needed with foreign
785                              lambda, and only output when init_lambda is not
786                              set in order to maintain compatibility of the
787                              dhdl.xvg file) */
788         write_pV     = true;
789     }
790     std::vector<std::string> setname(nsetsextend);
791
792     if (expand->elmcmove > elmcmoveNO)
793     {
794         /* state for the fep_vals, if we have alchemical sampling */
795         setname[s++] = "Thermodynamic state";
796     }
797
798     if (fep->edHdLPrintEnergy != edHdLPrintEnergyNO)
799     {
800         std::string energy;
801         switch (fep->edHdLPrintEnergy)
802         {
803             case edHdLPrintEnergyPOTENTIAL:
804                 energy = gmx::formatString("%s (%s)", "Potential Energy", unit_energy);
805                 break;
806             case edHdLPrintEnergyTOTAL:
807             case edHdLPrintEnergyYES:
808             default:
809                 energy = gmx::formatString("%s (%s)", "Total Energy", unit_energy);
810         }
811         setname[s++] = energy;
812     }
813
814     if (fep->dhdl_derivatives == edhdlderivativesYES)
815     {
816         for (i = 0; i < efptNR; i++)
817         {
818             if (fep->separate_dvdl[i])
819             {
820                 std::string derivative;
821                 if ( (fep->init_lambda >= 0)  && (n_lambda_terms == 1 ))
822                 {
823                     /* compatibility output */
824                     derivative = gmx::formatString("%s %s %.4f", dhdl, lambda, fep->init_lambda);
825                 }
826                 else
827                 {
828                     double lam = fep->init_lambda;
829                     if (fep->init_lambda < 0)
830                     {
831                         lam = fep->all_lambda[i][fep->init_fep_state];
832                     }
833                     derivative = gmx::formatString("%s %s = %.4f", dhdl, efpt_singular_names[i],
834                                                    lam);
835                 }
836                 setname[s++] = derivative;
837             }
838         }
839     }
840
841     if (fep->n_lambda > 0)
842     {
843         /* g_bar has to determine the lambda values used in this simulation
844          * from this xvg legend.
845          */
846
847         if (expand->elmcmove > elmcmoveNO)
848         {
849             nsetsbegin = 1;  /* for including the expanded ensemble */
850         }
851         else
852         {
853             nsetsbegin = 0;
854         }
855
856         if (fep->edHdLPrintEnergy != edHdLPrintEnergyNO)
857         {
858             nsetsbegin += 1;
859         }
860         nsetsbegin += nsets_dhdl;
861
862         for (i = fep->lambda_start_n; i < fep->lambda_stop_n; i++)
863         {
864             print_lambda_vector(fep, i, false, false, lambda_vec_str);
865             std::string buf;
866             if ( (fep->init_lambda >= 0)  && (n_lambda_terms == 1 ))
867             {
868                 /* for compatible dhdl.xvg files */
869                 buf = gmx::formatString("%s %s %s", deltag, lambda, lambda_vec_str);
870             }
871             else
872             {
873                 buf = gmx::formatString("%s %s to %s", deltag, lambda, lambda_vec_str);
874             }
875
876             if (ir->bSimTemp)
877             {
878                 /* print the temperature for this state if doing simulated annealing */
879                 buf += gmx::formatString("T = %g (%s)",
880                                          ir->simtempvals->temperatures[s-(nsetsbegin)],
881                                          unit_temp_K);
882             }
883             setname[s++] = buf;
884         }
885         if (write_pV)
886         {
887             setname[s++] = gmx::formatString("pV (%s)", unit_energy);
888         }
889
890         xvgrLegend(fp, setname, oenv);
891     }
892
893     return fp;
894 }
895
896 namespace gmx
897 {
898
899 void EnergyOutput::addDataAtEnergyStep(bool                    bDoDHDL,
900                                        bool                    bSum,
901                                        double                  time,
902                                        real                    tmass,
903                                        gmx_enerdata_t         *enerd,
904                                        t_state                *state,
905                                        t_lambda               *fep,
906                                        t_expanded             *expand,
907                                        matrix                  box,
908                                        tensor                  svir,
909                                        tensor                  fvir,
910                                        tensor                  vir,
911                                        tensor                  pres,
912                                        gmx_ekindata_t         *ekind,
913                                        rvec                    mu_tot,
914                                        const gmx::Constraints *constr)
915 {
916     int    j, k, kk, n, gid;
917     real   crmsd[2], tmp6[6];
918     real   bs[tricl_boxs_nm.size()], vol, dens, pv, enthalpy;
919     real   eee[egNR];
920     double store_dhdl[efptNR];
921     real   store_energy = 0;
922     real   tmp;
923
924     /* Do NOT use the box in the state variable, but the separate box provided
925      * as an argument. This is because we sometimes need to write the box from
926      * the last timestep to match the trajectory frames.
927      */
928     add_ebin_indexed(ebin_, ie_, gmx::ArrayRef<bool>(bEner_), enerd->term, bSum);
929     if (nCrmsd_)
930     {
931         crmsd[0] = constr->rmsd();
932         add_ebin(ebin_, iconrmsd_, nCrmsd_, crmsd, false);
933     }
934     if (bDynBox_)
935     {
936         int nboxs;
937         if (bTricl_)
938         {
939             bs[0] = box[XX][XX];
940             bs[1] = box[YY][YY];
941             bs[2] = box[ZZ][ZZ];
942             bs[3] = box[YY][XX];
943             bs[4] = box[ZZ][XX];
944             bs[5] = box[ZZ][YY];
945             nboxs = tricl_boxs_nm.size();
946         }
947         else
948         {
949             bs[0] = box[XX][XX];
950             bs[1] = box[YY][YY];
951             bs[2] = box[ZZ][ZZ];
952             nboxs = boxs_nm.size();
953         }
954         vol  = box[XX][XX]*box[YY][YY]*box[ZZ][ZZ];
955         dens = (tmass*AMU)/(vol*NANO*NANO*NANO);
956         add_ebin(ebin_, ib_, nboxs, bs, bSum);
957         add_ebin(ebin_, ivol_, 1, &vol, bSum);
958         add_ebin(ebin_, idens_, 1, &dens, bSum);
959
960         if (bDiagPres_)
961         {
962             /* This is pV (in kJ/mol).  The pressure is the reference pressure,
963                not the instantaneous pressure */
964             pv = vol*ref_p_/PRESFAC;
965
966             add_ebin(ebin_, ipv_, 1, &pv, bSum);
967             enthalpy = pv + enerd->term[F_ETOT];
968             add_ebin(ebin_, ienthalpy_, 1, &enthalpy, bSum);
969         }
970     }
971     if (bConstrVir_)
972     {
973         add_ebin(ebin_, isvir_, 9, svir[0], bSum);
974         add_ebin(ebin_, ifvir_, 9, fvir[0], bSum);
975     }
976     if (bPres_)
977     {
978         add_ebin(ebin_, ivir_, 9, vir[0], bSum);
979         add_ebin(ebin_, ipres_, 9, pres[0], bSum);
980         tmp = (pres[ZZ][ZZ]-(pres[XX][XX]+pres[YY][YY])*0.5)*box[ZZ][ZZ];
981         add_ebin(ebin_, isurft_, 1, &tmp, bSum);
982     }
983     if (epc_ == epcPARRINELLORAHMAN || epc_ == epcMTTK)
984     {
985         tmp6[0] = state->boxv[XX][XX];
986         tmp6[1] = state->boxv[YY][YY];
987         tmp6[2] = state->boxv[ZZ][ZZ];
988         tmp6[3] = state->boxv[YY][XX];
989         tmp6[4] = state->boxv[ZZ][XX];
990         tmp6[5] = state->boxv[ZZ][YY];
991         add_ebin(ebin_, ipc_, bTricl_ ? 6 : 3, tmp6, bSum);
992     }
993     if (bMu_)
994     {
995         add_ebin(ebin_, imu_, 3, mu_tot, bSum);
996     }
997     if (ekind && ekind->cosacc.cos_accel != 0)
998     {
999         vol  = box[XX][XX]*box[YY][YY]*box[ZZ][ZZ];
1000         dens = (tmass*AMU)/(vol*NANO*NANO*NANO);
1001         add_ebin(ebin_, ivcos_, 1, &(ekind->cosacc.vcos), bSum);
1002         /* 1/viscosity, unit 1/(kg m^-1 s^-1) */
1003         tmp = 1/(ekind->cosacc.cos_accel/(ekind->cosacc.vcos*PICO)
1004                  *dens*gmx::square(box[ZZ][ZZ]*NANO/(2*M_PI)));
1005         add_ebin(ebin_, ivisc_, 1, &tmp, bSum);
1006     }
1007     if (nE_ > 1)
1008     {
1009         n = 0;
1010         for (int i = 0; (i < nEg_); i++)
1011         {
1012             for (j = i; (j < nEg_); j++)
1013             {
1014                 gid = GID(i, j, nEg_);
1015                 for (k = kk = 0; (k < egNR); k++)
1016                 {
1017                     if (bEInd_[k])
1018                     {
1019                         eee[kk++] = enerd->grpp.ener[k][gid];
1020                     }
1021                 }
1022                 add_ebin(ebin_, igrp_[n], nEc_, eee, bSum);
1023                 n++;
1024             }
1025         }
1026     }
1027
1028     if (ekind)
1029     {
1030         for (int i = 0; (i < nTC_); i++)
1031         {
1032             tmp_r_[i] = ekind->tcstat[i].T;
1033         }
1034         add_ebin(ebin_, itemp_, nTC_, tmp_r_, bSum);
1035
1036         if (etc_ == etcNOSEHOOVER)
1037         {
1038             /* whether to print Nose-Hoover chains: */
1039             if (bPrintNHChains_)
1040             {
1041                 if (bNHC_trotter_)
1042                 {
1043                     for (int i = 0; (i < nTC_); i++)
1044                     {
1045                         for (j = 0; j < nNHC_; j++)
1046                         {
1047                             k                  = i*nNHC_+j;
1048                             tmp_r_[2*k]        = state->nosehoover_xi[k];
1049                             tmp_r_[2*k+1]      = state->nosehoover_vxi[k];
1050                         }
1051                     }
1052                     add_ebin(ebin_, itc_, mde_n_, tmp_r_, bSum);
1053
1054                     if (bMTTK_)
1055                     {
1056                         for (int i = 0; (i < nTCP_); i++)
1057                         {
1058                             for (j = 0; j < nNHC_; j++)
1059                             {
1060                                 k                  = i*nNHC_+j;
1061                                 tmp_r_[2*k]        = state->nhpres_xi[k];
1062                                 tmp_r_[2*k+1]      = state->nhpres_vxi[k];
1063                             }
1064                         }
1065                         add_ebin(ebin_, itcb_, mdeb_n_, tmp_r_, bSum);
1066                     }
1067                 }
1068                 else
1069                 {
1070                     for (int i = 0; (i < nTC_); i++)
1071                     {
1072                         tmp_r_[2*i]   = state->nosehoover_xi[i];
1073                         tmp_r_[2*i+1] = state->nosehoover_vxi[i];
1074                     }
1075                     add_ebin(ebin_, itc_, mde_n_, tmp_r_, bSum);
1076                 }
1077             }
1078         }
1079         else if (etc_ == etcBERENDSEN || etc_ == etcYES ||
1080                  etc_ == etcVRESCALE)
1081         {
1082             for (int i = 0; (i < nTC_); i++)
1083             {
1084                 tmp_r_[i] = ekind->tcstat[i].lambda;
1085             }
1086             add_ebin(ebin_, itc_, nTC_, tmp_r_, bSum);
1087         }
1088     }
1089
1090     if (ekind && nU_ > 1)
1091     {
1092         for (int i = 0; (i < nU_); i++)
1093         {
1094             copy_rvec(ekind->grpstat[i].u, tmp_v_[i]);
1095         }
1096         add_ebin(ebin_, iu_, 3*nU_, tmp_v_[0], bSum);
1097     }
1098
1099     ebin_increase_count(1, ebin_, bSum);
1100
1101     // BAR + thermodynamic integration values
1102     if ((fp_dhdl_ || dhc_) && bDoDHDL)
1103     {
1104         for (gmx::index i = 0; i < static_cast<gmx::index>(enerd->enerpart_lambda.size()) - 1; i++)
1105         {
1106             /* zero for simulated tempering */
1107             dE_[i] = enerd->enerpart_lambda[i+1]-enerd->enerpart_lambda[0];
1108             if (numTemperatures_ > 0)
1109             {
1110                 GMX_RELEASE_ASSERT(numTemperatures_ > state->fep_state, "Number of lambdas in state is bigger then in input record");
1111                 GMX_RELEASE_ASSERT(numTemperatures_ >= static_cast<gmx::index>(enerd->enerpart_lambda.size()) - 1, "Number of lambdas in energy data is bigger then in input record");
1112                 /* MRS: is this right, given the way we have defined the exchange probabilities? */
1113                 /* is this even useful to have at all? */
1114                 dE_[i] += (temperatures_[i]/
1115                            temperatures_[state->fep_state]-1.0)*
1116                     enerd->term[F_EKIN];
1117             }
1118         }
1119
1120         if (fp_dhdl_)
1121         {
1122             fprintf(fp_dhdl_, "%.4f", time);
1123             /* the current free energy state */
1124
1125             /* print the current state if we are doing expanded ensemble */
1126             if (expand->elmcmove > elmcmoveNO)
1127             {
1128                 fprintf(fp_dhdl_, " %4d", state->fep_state);
1129             }
1130             /* total energy (for if the temperature changes */
1131
1132             if (fep->edHdLPrintEnergy != edHdLPrintEnergyNO)
1133             {
1134                 switch (fep->edHdLPrintEnergy)
1135                 {
1136                     case edHdLPrintEnergyPOTENTIAL:
1137                         store_energy = enerd->term[F_EPOT];
1138                         break;
1139                     case edHdLPrintEnergyTOTAL:
1140                     case edHdLPrintEnergyYES:
1141                     default:
1142                         store_energy = enerd->term[F_ETOT];
1143                 }
1144                 fprintf(fp_dhdl_, " %#.8g", store_energy);
1145             }
1146
1147             if (fep->dhdl_derivatives == edhdlderivativesYES)
1148             {
1149                 for (int i = 0; i < efptNR; i++)
1150                 {
1151                     if (fep->separate_dvdl[i])
1152                     {
1153                         /* assumes F_DVDL is first */
1154                         fprintf(fp_dhdl_, " %#.8g", enerd->term[F_DVDL+i]);
1155                     }
1156                 }
1157             }
1158             for (int i = fep->lambda_start_n; i < fep->lambda_stop_n; i++)
1159             {
1160                 fprintf(fp_dhdl_, " %#.8g", dE_[i]);
1161             }
1162             if (bDynBox_ &&
1163                 bDiagPres_ &&
1164                 (epc_ != epcNO) &&
1165                 !enerd->enerpart_lambda.empty() &&
1166                 (fep->init_lambda < 0))
1167             {
1168                 fprintf(fp_dhdl_, " %#.8g", pv);  /* PV term only needed when
1169                                                           there are alternate state
1170                                                           lambda and we're not in
1171                                                           compatibility mode */
1172             }
1173             fprintf(fp_dhdl_, "\n");
1174             /* and the binary free energy output */
1175         }
1176         if (dhc_ && bDoDHDL)
1177         {
1178             int idhdl = 0;
1179             for (int i = 0; i < efptNR; i++)
1180             {
1181                 if (fep->separate_dvdl[i])
1182                 {
1183                     /* assumes F_DVDL is first */
1184                     store_dhdl[idhdl] = enerd->term[F_DVDL+i];
1185                     idhdl            += 1;
1186                 }
1187             }
1188             store_energy = enerd->term[F_ETOT];
1189             /* store_dh is dE */
1190             mde_delta_h_coll_add_dh(dhc_,
1191                                     static_cast<double>(state->fep_state),
1192                                     store_energy,
1193                                     pv,
1194                                     store_dhdl,
1195                                     dE_ + fep->lambda_start_n,
1196                                     time);
1197         }
1198     }
1199     ;
1200 }
1201
1202 void EnergyOutput::recordNonEnergyStep()
1203 {
1204     ebin_increase_count(1, ebin_, false);
1205 }
1206
1207 void EnergyOutput::printHeader(FILE *log, int64_t steps, double time)
1208 {
1209     char buf[22];
1210
1211     fprintf(log, "   %12s   %12s\n"
1212             "   %12s   %12.5f\n\n",
1213             "Step", "Time", gmx_step_str(steps, buf), time);
1214 }
1215
1216 void EnergyOutput::printStepToEnergyFile(ener_file *fp_ene, bool bEne, bool bDR, bool bOR,
1217                                          FILE *log,
1218                                          int64_t step, double time,
1219                                          t_fcdata *fcd,
1220                                          gmx::Awh *awh)
1221 {
1222     t_enxframe   fr;
1223     init_enxframe(&fr);
1224     fr.t            = time;
1225     fr.step         = step;
1226     fr.nsteps       = ebin_->nsteps;
1227     fr.dt           = delta_t_;
1228     fr.nsum         = ebin_->nsum;
1229     fr.nre          = (bEne) ? ebin_->nener : 0;
1230     fr.ener         = ebin_->e;
1231     int ndisre          = bDR ? fcd->disres.npair : 0;
1232     /* these are for the old-style blocks (1 subblock, only reals), because
1233        there can be only one per ID for these */
1234     int          nr[enxNR];
1235     int          id[enxNR];
1236     real        *block[enxNR];
1237     /* Optional additional old-style (real-only) blocks. */
1238     for (int i = 0; i < enxNR; i++)
1239     {
1240         nr[i] = 0;
1241     }
1242
1243     if (bOR && fcd->orires.nr > 0)
1244     {
1245         diagonalize_orires_tensors(&(fcd->orires));
1246         nr[enxOR]     = fcd->orires.nr;
1247         block[enxOR]  = fcd->orires.otav;
1248         id[enxOR]     = enxOR;
1249         nr[enxORI]    = (fcd->orires.oinsl != fcd->orires.otav) ?
1250             fcd->orires.nr : 0;
1251         block[enxORI] = fcd->orires.oinsl;
1252         id[enxORI]    = enxORI;
1253         nr[enxORT]    = fcd->orires.nex*12;
1254         block[enxORT] = fcd->orires.eig;
1255         id[enxORT]    = enxORT;
1256     }
1257
1258     /* whether we are going to write anything out: */
1259     if (fr.nre || ndisre || nr[enxOR] || nr[enxORI])
1260     {
1261         /* the old-style blocks go first */
1262         fr.nblock = 0;
1263         for (int i = 0; i < enxNR; i++)
1264         {
1265             if (nr[i] > 0)
1266             {
1267                 fr.nblock = i + 1;
1268             }
1269         }
1270         add_blocks_enxframe(&fr, fr.nblock);
1271         for (int b = 0; b < fr.nblock; b++)
1272         {
1273             add_subblocks_enxblock(&(fr.block[b]), 1);
1274             fr.block[b].id        = id[b];
1275             fr.block[b].sub[0].nr = nr[b];
1276 #if !GMX_DOUBLE
1277             fr.block[b].sub[0].type = xdr_datatype_float;
1278             fr.block[b].sub[0].fval = block[b];
1279 #else
1280             fr.block[b].sub[0].type = xdr_datatype_double;
1281             fr.block[b].sub[0].dval = block[b];
1282 #endif
1283         }
1284
1285         /* check for disre block & fill it. */
1286         if (ndisre > 0)
1287         {
1288             int db = fr.nblock;
1289             fr.nblock += 1;
1290             add_blocks_enxframe(&fr, fr.nblock);
1291
1292             add_subblocks_enxblock(&(fr.block[db]), 2);
1293             fr.block[db].id        = enxDISRE;
1294             fr.block[db].sub[0].nr = ndisre;
1295             fr.block[db].sub[1].nr = ndisre;
1296 #if !GMX_DOUBLE
1297             fr.block[db].sub[0].type = xdr_datatype_float;
1298             fr.block[db].sub[1].type = xdr_datatype_float;
1299             fr.block[db].sub[0].fval = fcd->disres.rt;
1300             fr.block[db].sub[1].fval = fcd->disres.rm3tav;
1301 #else
1302             fr.block[db].sub[0].type = xdr_datatype_double;
1303             fr.block[db].sub[1].type = xdr_datatype_double;
1304             fr.block[db].sub[0].dval = fcd->disres.rt;
1305             fr.block[db].sub[1].dval = fcd->disres.rm3tav;
1306 #endif
1307         }
1308         /* here we can put new-style blocks */
1309
1310         /* Free energy perturbation blocks */
1311         if (dhc_)
1312         {
1313             mde_delta_h_coll_handle_block(dhc_, &fr, fr.nblock);
1314         }
1315
1316         /* we can now free & reset the data in the blocks */
1317         if (dhc_)
1318         {
1319             mde_delta_h_coll_reset(dhc_);
1320         }
1321
1322         /* AWH bias blocks. */
1323         if (awh != nullptr)  // TODO: add boolean flag.
1324         {
1325             awh->writeToEnergyFrame(step, &fr);
1326         }
1327
1328         /* do the actual I/O */
1329         do_enx(fp_ene, &fr);
1330         if (fr.nre)
1331         {
1332             /* We have stored the sums, so reset the sum history */
1333             reset_ebin_sums(ebin_);
1334         }
1335     }
1336     free_enxframe(&fr);
1337     if (log)
1338     {
1339         if (bOR && fcd->orires.nr > 0)
1340         {
1341             print_orires_log(log, &(fcd->orires));
1342         }
1343
1344         fprintf(log, "   Energies (%s)\n", unit_energy);
1345         pr_ebin(log, ebin_, ie_, f_nre_+nCrmsd_, 5, eprNORMAL, true);
1346         fprintf(log, "\n");
1347     }
1348 }
1349
1350 void EnergyOutput::printAnnealingTemperatures(FILE *log, SimulationGroups *groups, t_grpopts *opts)
1351 {
1352     if (log)
1353     {
1354         if (opts)
1355         {
1356             for (int i = 0; i < opts->ngtc; i++)
1357             {
1358                 if (opts->annealing[i] != eannNO)
1359                 {
1360                     fprintf(log, "Current ref_t for group %s: %8.1f\n",
1361                             *(groups->groupNames[groups->groups[SimulationAtomGroupType::TemperatureCoupling][i]]),
1362                             opts->ref_t[i]);
1363                 }
1364             }
1365             fprintf(log, "\n");
1366         }
1367     }
1368 }
1369
1370 void EnergyOutput::printAverages(FILE *log, const SimulationGroups *groups)
1371 {
1372     if (ebin_->nsum_sim <= 0)
1373     {
1374         if (log)
1375         {
1376             fprintf(log, "Not enough data recorded to report energy averages\n");
1377         }
1378         return;
1379     }
1380     if (log)
1381     {
1382
1383         char buf1[22], buf2[22];
1384
1385         fprintf(log, "\t<======  ###############  ==>\n");
1386         fprintf(log, "\t<====  A V E R A G E S  ====>\n");
1387         fprintf(log, "\t<==  ###############  ======>\n\n");
1388
1389         fprintf(log, "\tStatistics over %s steps using %s frames\n",
1390                 gmx_step_str(ebin_->nsteps_sim, buf1),
1391                 gmx_step_str(ebin_->nsum_sim, buf2));
1392         fprintf(log, "\n");
1393
1394         fprintf(log, "   Energies (%s)\n", unit_energy);
1395         pr_ebin(log, ebin_, ie_, f_nre_+nCrmsd_, 5, eprAVER, true);
1396         fprintf(log, "\n");
1397
1398         if (bDynBox_)
1399         {
1400             pr_ebin(log, ebin_, ib_, bTricl_ ? tricl_boxs_nm.size() : boxs_nm.size(), 5,
1401                     eprAVER, true);
1402             fprintf(log, "\n");
1403         }
1404         if (bConstrVir_)
1405         {
1406             fprintf(log, "   Constraint Virial (%s)\n", unit_energy);
1407             pr_ebin(log, ebin_, isvir_, 9, 3, eprAVER, false);
1408             fprintf(log, "\n");
1409             fprintf(log, "   Force Virial (%s)\n", unit_energy);
1410             pr_ebin(log, ebin_, ifvir_, 9, 3, eprAVER, false);
1411             fprintf(log, "\n");
1412         }
1413         if (bPres_)
1414         {
1415             fprintf(log, "   Total Virial (%s)\n", unit_energy);
1416             pr_ebin(log, ebin_, ivir_, 9, 3, eprAVER, false);
1417             fprintf(log, "\n");
1418             fprintf(log, "   Pressure (%s)\n", unit_pres_bar);
1419             pr_ebin(log, ebin_, ipres_, 9, 3, eprAVER, false);
1420             fprintf(log, "\n");
1421         }
1422         if (bMu_)
1423         {
1424             fprintf(log, "   Total Dipole (%s)\n", unit_dipole_D);
1425             pr_ebin(log, ebin_, imu_, 3, 3, eprAVER, false);
1426             fprintf(log, "\n");
1427         }
1428
1429         if (nE_ > 1)
1430         {
1431             int padding = 8 - strlen(unit_energy);
1432             fprintf(log, "%*sEpot (%s)   ", padding, "", unit_energy);
1433             for (int i = 0; (i < egNR); i++)
1434             {
1435                 if (bEInd_[i])
1436                 {
1437                     fprintf(log, "%12s   ", egrp_nm[i]);
1438                 }
1439             }
1440             fprintf(log, "\n");
1441
1442             int n = 0;
1443             for (int i = 0; (i < nEg_); i++)
1444             {
1445                 int ni = groups->groups[SimulationAtomGroupType::EnergyOutput][i];
1446                 for (int j = i; (j < nEg_); j++)
1447                 {
1448                     int nj      = groups->groups[SimulationAtomGroupType::EnergyOutput][j];
1449                     int padding = 14 - (strlen(*(groups->groupNames[ni])) +
1450                                         strlen(*(groups->groupNames[nj])));
1451                     fprintf(log, "%*s%s-%s", padding, "",
1452                             *(groups->groupNames[ni]),
1453                             *(groups->groupNames[nj]));
1454                     pr_ebin(log, ebin_, igrp_[n], nEc_, nEc_, eprAVER,
1455                             false);
1456                     n++;
1457                 }
1458             }
1459             fprintf(log, "\n");
1460         }
1461         if (nTC_ > 1)
1462         {
1463             pr_ebin(log, ebin_, itemp_, nTC_, 4, eprAVER, true);
1464             fprintf(log, "\n");
1465         }
1466         if (nU_ > 1)
1467         {
1468             fprintf(log, "%15s   %12s   %12s   %12s\n",
1469                     "Group", "Ux", "Uy", "Uz");
1470             for (int i = 0; (i < nU_); i++)
1471             {
1472                 int ni = groups->groups[SimulationAtomGroupType::Acceleration][i];
1473                 fprintf(log, "%15s", *groups->groupNames[ni]);
1474                 pr_ebin(log, ebin_, iu_+3*i, 3, 3, eprAVER, false);
1475             }
1476             fprintf(log, "\n");
1477         }
1478     }
1479 }
1480
1481 void EnergyOutput::fillEnergyHistory(energyhistory_t *enerhist) const
1482 {
1483     const t_ebin * const ebin = ebin_;
1484
1485     enerhist->nsteps     = ebin->nsteps;
1486     enerhist->nsum       = ebin->nsum;
1487     enerhist->nsteps_sim = ebin->nsteps_sim;
1488     enerhist->nsum_sim   = ebin->nsum_sim;
1489
1490     if (ebin->nsum > 0)
1491     {
1492         /* This will only actually resize the first time */
1493         enerhist->ener_ave.resize(ebin->nener);
1494         enerhist->ener_sum.resize(ebin->nener);
1495
1496         for (int i = 0; i < ebin->nener; i++)
1497         {
1498             enerhist->ener_ave[i] = ebin->e[i].eav;
1499             enerhist->ener_sum[i] = ebin->e[i].esum;
1500         }
1501     }
1502
1503     if (ebin->nsum_sim > 0)
1504     {
1505         /* This will only actually resize the first time */
1506         enerhist->ener_sum_sim.resize(ebin->nener);
1507
1508         for (int i = 0; i < ebin->nener; i++)
1509         {
1510             enerhist->ener_sum_sim[i] = ebin->e_sim[i].esum;
1511         }
1512     }
1513     if (dhc_)
1514     {
1515         mde_delta_h_coll_update_energyhistory(dhc_, enerhist);
1516     }
1517 }
1518
1519 void EnergyOutput::restoreFromEnergyHistory(const energyhistory_t &enerhist)
1520 {
1521     unsigned int nener = static_cast<unsigned int>(ebin_->nener);
1522
1523     if ((enerhist.nsum     > 0 && nener != enerhist.ener_sum.size()) ||
1524         (enerhist.nsum_sim > 0 && nener != enerhist.ener_sum_sim.size()))
1525     {
1526         gmx_fatal(FARGS, "Mismatch between number of energies in run input (%u) and checkpoint file (%zu or %zu).",
1527                   nener, enerhist.ener_sum.size(), enerhist.ener_sum_sim.size());
1528     }
1529
1530     ebin_->nsteps     = enerhist.nsteps;
1531     ebin_->nsum       = enerhist.nsum;
1532     ebin_->nsteps_sim = enerhist.nsteps_sim;
1533     ebin_->nsum_sim   = enerhist.nsum_sim;
1534
1535     for (int i = 0; i < ebin_->nener; i++)
1536     {
1537         ebin_->e[i].eav  =
1538             (enerhist.nsum > 0 ? enerhist.ener_ave[i] : 0);
1539         ebin_->e[i].esum =
1540             (enerhist.nsum > 0 ? enerhist.ener_sum[i] : 0);
1541         ebin_->e_sim[i].esum =
1542             (enerhist.nsum_sim > 0 ? enerhist.ener_sum_sim[i] : 0);
1543     }
1544     if (dhc_)
1545     {
1546         mde_delta_h_coll_restore_energyhistory(dhc_, enerhist.deltaHForeignLambdas.get());
1547     }
1548 }
1549
1550 int EnergyOutput::numEnergyTerms() const
1551 {
1552     return ebin_->nener;
1553 }
1554
1555 } // namespace gmx