Add lambda state to dhdl.xvg with AWH fep
[alexxy/gromacs.git] / src / gromacs / mdlib / energyoutput.h
index 7e705012217869522fa931058f4bc504d27e4b4c..54ae8b01b278139a37aa3a74bf52cae7ac09b217 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2019, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020,2021, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
  * To help us fund GROMACS development, we humbly ask that you cite
  * the research papers on the package. Check out http://www.gromacs.org.
  */
+/*! \libinternal \file
+ * \brief Header for the code that writes energy-like quantities.
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \author Paul Bauer <paul.bauer.q@gmail.com>
+ * \author Artem Zhmurov <zhmurov@gmail.com>
+ *
+ * \ingroup module_mdlib
+ * \inlibraryapi
+ */
 #ifndef GMX_MDLIB_ENERGYOUTPUT_H
 #define GMX_MDLIB_ENERGYOUTPUT_H
 
 #include <cstdio>
 
+#include <memory>
+
+#include "gromacs/math/vectypes.h"
+#include "gromacs/mdtypes/md_enums.h"
 #include "gromacs/mdtypes/enerdata.h"
+#include "gromacs/topology/ifunc.h"
+#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/real.h"
 
 class energyhistory_t;
 struct ener_file;
-struct gmx_ekindata_t;
+class gmx_ekindata_t;
 struct gmx_enerdata_t;
-struct gmx_groups_t;
+struct SimulationGroups;
 struct gmx_mtop_t;
 struct gmx_output_env_t;
+struct pull_t;
 struct t_ebin;
-struct t_expanded;
 struct t_fcdata;
 struct t_grpopts;
 struct t_inputrec;
 struct t_lambda;
 class t_state;
 
+struct t_mde_delta_h_coll;
+
 namespace gmx
 {
 class Awh;
 class Constraints;
-}
+struct MDModulesNotifiers;
+enum class StartingBehavior;
+} // namespace gmx
 
-extern const char *egrp_nm[egNR+1];
+//! \brief Printed names for intergroup energies
+const char* enumValueToString(NonBondedEnergyTerms enumValue);
 
-/* delta_h block type enum: the kinds of energies written out. */
+/* \brief delta_h block type enum: the kinds of energies written out. */
 enum
 {
-    dhbtDH   = 0, /* delta H BAR energy difference*/
-    dhbtDHDL = 1, /* dH/dlambda derivative */
-    dhbtEN,       /* System energy */
-    dhbtPV,       /* pV term */
-    dhbtEXPANDED, /* expanded ensemble statistics */
+    //! Delta H BAR energy difference
+    dhbtDH = 0,
+    //! dH/dlambda derivative
+    dhbtDHDL = 1,
+    //! System energy
+    dhbtEN,
+    //! pV term
+    dhbtPV,
+    //! Expanded ensemble statistics
+    dhbtEXPANDED,
+    //! Total number of energy types in this enum
     dhbtNR
 };
 
 namespace gmx
 {
+class EnergyDriftTracker;
 
-// TODO remove use of detail namespace when removing t_mdebin in
-// favour of an Impl class.
-namespace detail
+/*! \internal
+ * \brief Arrays connected to Pressure and Temperature coupling
+ */
+struct PTCouplingArrays
 {
-struct t_mdebin;
-}
-
-/* The functions & data structures here determine the content for outputting
-   the .edr file; the file format and actual writing is done with functions
-   defined in enxio.h */
+    //! Box velocities for Parrinello-Rahman P-coupling.
+    const rvec* boxv;
+    //! Nose-Hoover coordinates.
+    ArrayRef<const double> nosehoover_xi;
+    //! Nose-Hoover velocities.
+    ArrayRef<const double> nosehoover_vxi;
+    //! Pressure Nose-Hoover coordinates.
+    ArrayRef<const double> nhpres_xi;
+    //! Pressure Nose-Hoover velocities.
+    ArrayRef<const double> nhpres_vxi;
+};
 
+/* Energy output class
+ *
+ * This is the collection of energy averages collected during mdrun, and to
+ * be written out to the .edr file.
+ *
+ * \todo Use more std containers.
+ * \todo Write free-energy output also to energy file (after adding more tests)
+ */
 class EnergyOutput
 {
-    public:
-        EnergyOutput();
-        /*! \brief Initiate MD energy bin
-         *
-         * This second phase of construction is needed until we have
-         * modules that understand how to request output from
-         * EnergyOutput.
-         *
-         * \todo Refactor to separate a function to write the energy
-         * file header. Perhaps transform the remainder into a factory
-         * function.
-         */
-        void prepare(ener_file        *fp_ene,
-                     const gmx_mtop_t *mtop,
-                     const t_inputrec *ir,
-                     FILE             *fp_dhdl,
-                     bool              isRerun = false);
-        ~EnergyOutput();
-        /*! \brief Update the averaging structures.
-         *
-         * Called every step on which the energies are evaluated. */
-        void addDataAtEnergyStep(bool                    bDoDHDL,
-                                 bool                    bSum,
-                                 double                  time,
-                                 real                    tmass,
-                                 gmx_enerdata_t         *enerd,
-                                 t_state                *state,
-                                 t_lambda               *fep,
-                                 t_expanded             *expand,
-                                 matrix                  lastbox,
-                                 tensor                  svir,
-                                 tensor                  fvir,
-                                 tensor                  vir,
-                                 tensor                  pres,
-                                 gmx_ekindata_t         *ekind,
-                                 rvec                    mu_tot,
-                                 const gmx::Constraints *constr);
-        /*! \brief Updated the averaging structures
-         *
-         * Called every step on which the energies are not evaluated.
-         *
-         * \todo This schedule is known in advance, and should be made
-         * an intrinsic behaviour of EnergyOutput, rather than being
-         * wastefully called every step. */
-        void recordNonEnergyStep();
-
-        /*! \brief Help write quantites to the energy file
-         *
-         * \todo Perhaps this responsibility should involve some other
-         * object visiting all the contributing objects. */
-        void printStepToEnergyFile(ener_file *fp_ene, bool bEne, bool bDR, bool bOR,
-                                   FILE *log,
-                                   int64_t step, double time,
-                                   int mode,
-                                   t_fcdata *fcd,
-                                   gmx_groups_t *groups, t_grpopts *opts,
-                                   gmx::Awh *awh);
-        /*! \brief Get the number of energy terms recorded.
-         *
-         * \todo Refactor this to return the expected output size,
-         * rather than exposing the implementation details about
-         * energy terms. */
-        int numEnergyTerms() const;
-        /*! \brief Getter used for testing t_ebin
-         *
-         * \todo Find a better approach for this. */
-        t_ebin *getEbin();
-
-        /* Between .edr writes, the averages are history dependent,
-           and that history needs to be retained in checkpoints.
-           These functions set/read the energyhistory_t class
-           that is written to checkpoints in checkpoint.c */
-
-        //! Fill the energyhistory_t data.
-        void fillEnergyHistory(energyhistory_t * enerhist) const;
-        //! Restore from energyhistory_t data.
-        void restoreFromEnergyHistory(const energyhistory_t &enerhist);
-
-    private:
-        // TODO transform this into an impl class.
-        detail::t_mdebin *mdebin = nullptr;
-};
+public:
+    /*! \brief Initiate MD energy bin
+     *
+     * \param[in] fp_ene     Energy output file.
+     * \param[in] mtop       Topology.
+     * \param[in] inputrec   Input parameters.
+     * \param[in] pull_work  Pulling simulations data
+     * \param[in] fp_dhdl    FEP file.
+     * \param[in] isRerun    Is this is a rerun instead of the simulations.
+     * \param[in] startingBehavior  Run starting behavior.
+     * \param[in] simulationsShareState  Tells whether the physical state is shared over simulations
+     * \param[in] mdModulesNotifiers Notifications to MD modules.
+     */
+    EnergyOutput(ener_file*                fp_ene,
+                 const gmx_mtop_t&         mtop,
+                 const t_inputrec&         inputrec,
+                 const pull_t*             pull_work,
+                 FILE*                     fp_dhdl,
+                 bool                      isRerun,
+                 StartingBehavior          startingBehavior,
+                 bool                      simulationsShareState,
+                 const MDModulesNotifiers& mdModulesNotifiers);
 
-} // namespace gmx
+    ~EnergyOutput();
 
-//! Open the dhdl file for output
-FILE *open_dhdl(const char *filename, const t_inputrec *ir,
-                const gmx_output_env_t *oenv);
+    /*! \brief Update the averaging structures.
+     *
+     * Called every step on which the thermodynamic values are evaluated.
+     *
+     * \param[in] bDoDHDL           Whether the FEP is enabled.
+     * \param[in] bSum              If this stepshould be recorded to compute sums and averages.
+     * \param[in] time              Current simulation time.
+     * \param[in] tmass             Total mass
+     * \param[in] enerd             Energy data object.
+     * \param[in] fep               FEP data.
+     * \param[in] lastbox           PBC data.
+     * \param[in] ptCouplingArrays  Arrays connected to pressure and temperature coupling.
+     * \param[in] fep_state         The current alchemical state we are in.
+     * \param[in] vir               Total virial.
+     * \param[in] pres              Pressure.
+     * \param[in] ekind             Kinetic energy data.
+     * \param[in] mu_tot            Total dipole.
+     * \param[in] constr            Constraints object to get RMSD from (for LINCS only).
+     */
+    void addDataAtEnergyStep(bool                    bDoDHDL,
+                             bool                    bSum,
+                             double                  time,
+                             real                    tmass,
+                             const gmx_enerdata_t*   enerd,
+                             const t_lambda*         fep,
+                             const matrix            lastbox,
+                             PTCouplingArrays        ptCouplingArrays,
+                             int                     fep_state,
+                             const tensor            vir,
+                             const tensor            pres,
+                             const gmx_ekindata_t*   ekind,
+                             const rvec              mu_tot,
+                             const gmx::Constraints* constr);
 
-namespace gmx
-{
+    /*! \brief Update the data averaging structure counts.
+     *
+     * Updates the number of steps, the values have not being computed.
+     */
+    void recordNonEnergyStep();
+
+    /*! \brief Writes current quantites to log and energy files.
+     *
+     * Prints current values of energies, pressure, temperature, restraint
+     * data, etc. to energy output file and to the log file (if not nullptr).
+     *
+     * This function only does something useful when bEne || bDR || bOR || log.
+     *
+     * \todo Perhaps this responsibility should involve some other
+     *       object visiting all the contributing objects.
+     *
+     * \param[in] fp_ene   Energy file for the output.
+     * \param[in] bEne     If it is a step for energy output or last step.
+     * \param[in] bDR      If it is a step of writing distance restraints.
+     * \param[in] bOR      If it is a step of writing orientation restraints.
+     * \param[in] log      Pointer to the log file.
+     * \param[in] step     Current step.
+     * \param[in] time     Current simulation time.
+     * \param[in] fcd      Bonded force computation data,
+     *                     including orientation and distance restraints.
+     * \param[in] awh      AWH data.
+     */
+    void printStepToEnergyFile(ener_file* fp_ene,
+                               bool       bEne,
+                               bool       bDR,
+                               bool       bOR,
+                               FILE*      log,
+                               int64_t    step,
+                               double     time,
+                               t_fcdata*  fcd,
+                               gmx::Awh*  awh);
+
+    /*! \brief Print reference temperatures for annealing groups.
+     *
+     * Nothing is done if log is nullptr.
+     *
+     * \param[in] log     Log file to print to.
+     * \param[in] groups  Information on atom groups.
+     * \param[in] opts    Atom temperature coupling groups options
+     *                    (annealing is done by groups).
+     */
+    static void printAnnealingTemperatures(FILE* log, const SimulationGroups* groups, const t_grpopts* opts);
+
+    /*! \brief Prints average values to log file.
+     *
+     * This is called at the end of the simulation run to print accumulated average values.
+     * Nothing it done if log is nullptr.
+     *
+     * \param[in]   log      Where to print.
+     * \param[in]   groups   Atom groups.
+     */
+    void printAverages(FILE* log, const SimulationGroups* groups);
+
+    /*! \brief Get the number of thermodynamic terms recorded.
+     *
+     * \todo Refactor this to return the expected output size,
+     *       rather than exposing the implementation details about
+     *       thermodynamic terms.
+     *
+     * \returns Number of thermodynamic terms.
+     */
+    int numEnergyTerms() const;
+
+    /*! \brief Fill the energyhistory_t data.
+     *
+     * Between .edr writes, the averages are history dependent,
+     * and that history needs to be retained in checkpoints.
+     * These functions set/read the energyhistory_t class
+     * that is written to checkpoints.
+     *
+     * \param[out] enerhist  Energy history data structure.
+     */
+    void fillEnergyHistory(energyhistory_t* enerhist) const;
+
+    /*! \brief Restore from energyhistory_t data.
+     *
+     * \param[in] enerhist  Energy history data structure.
+     */
+    void restoreFromEnergyHistory(const energyhistory_t& enerhist);
 
-//! Print an energy-output header to the log file
-void print_ebin_header(FILE *log, int64_t steps, double time);
+    //! Print an output header to the log file.
+    static void printHeader(FILE* log, int64_t steps, double time);
+
+    /*! \brief Print conserved energy drift message to \p fplog
+     *
+     * Note that this is only over the current run (times are printed),
+     * this is not from the original start time for runs with continuation.
+     * This has the advantage that one can find if conservation issues are
+     * from the current run with the current settings on the current hardware.
+     */
+    void printEnergyConservation(FILE* fplog, int simulationPart, bool usingMdIntegrator) const;
+
+private:
+    //! Timestep
+    double delta_t_ = 0;
+
+    //! Structure to store energy components and their running averages
+    t_ebin* ebin_ = nullptr;
+
+    //! Is the periodic box triclinic
+    bool bTricl_ = false;
+    //! NHC trotter is used
+    bool bNHC_trotter_ = false;
+    //! If Nose-Hoover chains should be printed
+    bool bPrintNHChains_ = false;
+    //! If MTTK integrator was used
+    bool bMTTK_ = false;
+
+    //! Temperature control scheme
+    TemperatureCoupling etc_ = TemperatureCoupling::No;
+
+    //! Which of the main energy terms should be printed
+    bool bEner_[F_NRE] = { false };
+    //! Index for main energy terms
+    int ie_ = 0;
+    //! Number of energy terms from F_NRE list to be saved (i.e. number of 'true' in bEner)
+    int f_nre_ = 0;
+
+    //! Index for constraints RMSD
+    int iconrmsd_ = 0;
+    /* !\brief How many constraints RMSD terms there are.
+     * Usually 1 if LINCS is used and 0 otherwise)
+     * nCrmsd > 0 indicates when constraints RMSD is saves, hence no boolean
+     */
+    int nCrmsd_ = 0;
+
+    //! Is the periodic box dynamic
+    bool bDynBox_ = false;
+    //! Index for box dimensions
+    int ib_ = 0;
+    //! Index for box volume
+    int ivol_ = 0;
+    //! Index for density
+    int idens_ = 0;
+    //! Triclinic box and not a rerun
+    bool bDiagPres_ = false;
+    //! Reference pressure, averaged over dimensions
+    real ref_p_ = 0.0;
+    //! Index for thermodynamic work (pV)
+    int ipv_ = 0;
+    //! Index for entalpy (pV + total energy)
+    int ienthalpy_ = 0;
+
+    //! If we have pressure computed
+    bool bPres_ = false;
+    //! Index for total virial
+    int ivir_ = 0;
+    //! Index for pressure
+    int ipres_ = 0;
+    /*! \brief Index for surface tension
+     * [(pres[ZZ][ZZ]-(pres[XX][XX]+pres[YY][YY])*0.5)*box[ZZ][ZZ]]*/
+    int isurft_ = 0;
+
+    //! Pressure control scheme
+    PressureCoupling epc_ = PressureCoupling::No;
+    //! Index for velocity of the box borders
+    int ipc_ = 0;
+
+    //! If dipole was calculated
+    bool bMu_ = false;
+    //! Index for the dipole
+    int imu_ = 0;
+
+    //! Index for coseine acceleration used for viscocity calculation
+    int ivcos_ = 0;
+    //! Index for viscocity
+    int ivisc_ = 0;
+
+    //! Which energy terms from NonBondedEnergyTerms list should be printed in group-to-group block
+    gmx::EnumerationArray<NonBondedEnergyTerms, bool> bEInd_;
+    //! Number of energy terms to be printed (these, for which bEInd[] == true)
+    int nEc_ = 0;
+    //! Number of energy output groups
+    int nEg_ = 0;
+    //! Number of intergroup energy sets to be printed for each energy term (nE = (nEg*(nEg+1))/2)
+    int nE_ = 0;
+    //! Indexes for integroup energy sets (each set with nEc energies)
+    std::vector<int> igrp_;
+
+    //! Number of temperature coupling groups
+    int nTC_ = 0;
+    //! Index for temperature
+    int itemp_ = 0;
+
+    //! Number of Nose-Hoover chains
+    int nNHC_ = 0;
+    //! Number of temperature coupling coefficients in case of NH Chains
+    int mde_n_ = 0;
+    //! Index for temperature coupling coefficient in case of NH chains
+    int itc_ = 0;
+
+    //! Number of temperature coupling terms if the temperature control is dealt by barostat (MTTK case)
+    int nTCP_ = 0;
+    //! Scalling factors for temperaturs control in MTTK
+    int mdeb_n_ = 0;
+    //! Index for scalling factor of MTTK
+    int itcb_ = 0;
+
+    //! Array to accumulate values during update
+    std::vector<real> tmp_r_;
+
+    //! The dhdl.xvg output file
+    FILE* fp_dhdl_ = nullptr;
+    //! Whether the free-energy lambda moves dynamically between lambda states
+    bool haveFepLambdaMoves_;
+    //! Energy components for dhdl.xvg output
+    std::vector<double> dE_;
+    //! The delta U components (raw data + histogram)
+    std::unique_ptr<t_mde_delta_h_coll> dhc_;
+    //! Temperatures for simulated tempering groups
+    std::vector<real> temperatures_;
+
+    //! For tracking the conserved or total energy
+    std::unique_ptr<EnergyDriftTracker> conservedEnergyTracker_;
+};
 
 } // namespace gmx
 
+//! Open the dhdl file for output
+FILE* open_dhdl(const char* filename, const t_inputrec* ir, const gmx_output_env_t* oenv);
+
 #endif