Make essential dynamics a C++ type.
authorChristian Blau <cblau@gwdg.de>
Mon, 6 Aug 2018 15:18:02 +0000 (17:18 +0200)
committerChristian Blau <cblau@gwdg.de>
Wed, 8 Aug 2018 12:08:42 +0000 (14:08 +0200)
Confer also the reform of the rotational pull data, Ic03919f68c, for the
conversion strategy for gmx_edsam.

Part of #2590

Change-Id: Iece42512a8c5222d86ab8545ce2fc12aa1c6ffc7

src/gromacs/essentialdynamics/edsam.cpp
src/gromacs/essentialdynamics/edsam.h
src/gromacs/mdlib/constr.cpp
src/gromacs/mdrun/md.cpp

index e5b3e322f801c9a491ce69f4b37b79218cf323f8..c4d16a0e3906bf153a51aeb2c12fe2ea3b0adf96 100644 (file)
@@ -189,14 +189,24 @@ typedef struct edpar
 } t_edpar;
 
 
-typedef struct gmx_edsam
+struct gmx_edsam
 {
-    int            eEDtype;       /* Type of ED: see enums above          */
-    FILE          *edo;           /* output file pointer                  */
-    t_edpar       *edpar;
-    gmx_bool       bFirst;
-} t_gmx_edsam;
-
+    ~gmx_edsam();
+    int            eEDtype = eEDnone;       /* Type of ED: see enums above          */
+    FILE          *edo     = nullptr;       /* output file pointer                  */
+    t_edpar       *edpar   = nullptr;
+    gmx_bool       bFirst  = false;
+};
+gmx_edsam::~gmx_edsam()
+{
+    if (edo)
+    {
+        /* edo is opened sometimes with xvgropen, sometimes with
+         * gmx_fio_fopen, so we use the least common denominator for
+         * closing. */
+        gmx_fio_fclose(edo);
+    }
+}
 
 struct t_do_edsam
 {
@@ -227,15 +237,33 @@ struct t_ed_buffer
     struct t_do_radcon *            do_radcon;
 };
 
+namespace gmx
+{
+class EssentialDynamics::Impl
+{
+    public:
+        // TODO: move all fields from gmx_edsam here and remove gmx_edsam
+        gmx_edsam essentialDynamics_;
+};
+EssentialDynamics::EssentialDynamics() : impl_(new Impl)
+{
+}
+EssentialDynamics::~EssentialDynamics() = default;
+
+gmx_edsam *EssentialDynamics::getLegacyED()
+{
+    return &impl_->essentialDynamics_;
+}
+} // namespace gmx
 
 /* Function declarations */
 static void fit_to_reference(rvec *xcoll, rvec transvec, matrix rotmat, t_edpar *edi);
 static void translate_and_rotate(rvec *x, int nat, rvec transvec, matrix rotmat);
 static real rmsd_from_structure(rvec *x, struct gmx_edx *s);
 static int read_edi_file(const char *fn, t_edpar *edi, int nr_mdatoms);
-static void crosscheck_edi_file_vs_checkpoint(gmx_edsam_t ed, edsamhistory_t *EDstate);
-static void init_edsamstate(gmx_edsam_t ed, edsamhistory_t *EDstate);
-static void write_edo_legend(gmx_edsam_t ed, int nED, const gmx_output_env_t *oenv);
+static void crosscheck_edi_file_vs_checkpoint(const gmx_edsam &ed, edsamhistory_t *EDstate);
+static void init_edsamstate(gmx_edsam * ed, edsamhistory_t *EDstate);
+static void write_edo_legend(gmx_edsam * ed, int nED, const gmx_output_env_t *oenv);
 /* End function declarations */
 
 /* Define formats for the column width in the output file */
@@ -1021,7 +1049,7 @@ extern void do_flood(const t_commrec  *cr,
 
 /* Called by init_edi, configure some flooding related variables and structures,
  * print headers to output files */
-static void init_flood(t_edpar *edi, gmx_edsam_t ed, real dt)
+static void init_flood(t_edpar *edi, gmx_edsam * ed, real dt)
 {
     int i;
 
@@ -1104,7 +1132,7 @@ static void get_flood_energies(t_edpar *edi, real Vfl[], int nnames)
  * with the essential dynamics data found in the checkpoint file (if present).
  * gmx make_edi can be used to create an .edi input file.
  */
-static gmx_edsam_t ed_open(
+static std::unique_ptr<gmx::EssentialDynamics> ed_open(
         int                     natoms,
         ObservablesHistory     *oh,
         const char             *ediFileName,
@@ -1113,12 +1141,10 @@ static gmx_edsam_t ed_open(
         const gmx_output_env_t *oenv,
         const t_commrec        *cr)
 {
-    gmx_edsam_t ed;
+    auto        edHandle = gmx::compat::make_unique<gmx::EssentialDynamics>();
+    auto        ed       = edHandle->getLegacyED();
     int         nED;
 
-    /* Allocate space for the ED data structure */
-    snew(ed, 1);
-
     /* We want to perform ED (this switch might later be upgraded to eEDflood) */
     ed->eEDtype = eEDedsam;
 
@@ -1139,7 +1165,7 @@ static gmx_edsam_t ed_open(
         /* Make sure the checkpoint was produced in a run using this .edi file */
         if (EDstate->bFromCpt)
         {
-            crosscheck_edi_file_vs_checkpoint(ed, EDstate);
+            crosscheck_edi_file_vs_checkpoint(*ed, EDstate);
         }
         else
         {
@@ -1163,7 +1189,7 @@ static gmx_edsam_t ed_open(
             write_edo_legend(ed, EDstate->nED, oenv);
         }
     }
-    return ed;
+    return edHandle;
 }
 
 
@@ -1243,7 +1269,7 @@ static void bc_ed_vecs(const t_commrec *cr, t_eigvec *ev, int length, gmx_bool b
 
 /* Broadcasts the ED / flooding data to other nodes
  * and allocates memory where needed */
-static void broadcast_ed_data(const t_commrec *cr, gmx_edsam_t ed, int numedis)
+static void broadcast_ed_data(const t_commrec *cr, gmx_edsam * ed, int numedis)
 {
     int      nr;
     t_edpar *edi;
@@ -2295,7 +2321,7 @@ static void copyEvecReference(t_eigvec* floodvecs)
 
 /* Call on MASTER only. Check whether the essential dynamics / flooding
  * groups of the checkpoint file are consistent with the provided .edi file. */
-static void crosscheck_edi_file_vs_checkpoint(gmx_edsam_t ed, edsamhistory_t *EDstate)
+static void crosscheck_edi_file_vs_checkpoint(const gmx_edsam &ed, edsamhistory_t *EDstate)
 {
     t_edpar *edi = nullptr;    /* points to a single edi data set */
     int      edinum;
@@ -2310,7 +2336,7 @@ static void crosscheck_edi_file_vs_checkpoint(gmx_edsam_t ed, edsamhistory_t *ED
                   "from without a checkpoint.\n");
     }
 
-    edi    = ed->edpar;
+    edi    = ed.edpar;
     edinum = 0;
     while (edi != nullptr)
     {
@@ -2347,7 +2373,7 @@ static void crosscheck_edi_file_vs_checkpoint(gmx_edsam_t ed, edsamhistory_t *ED
  * c) in any case, for subsequent checkpoint writing, we set the pointers in
  * edsamstate to the x_old arrays, which contain the correct PBC representation of
  * all ED structures at the last time step. */
-static void init_edsamstate(gmx_edsam_t ed, edsamhistory_t *EDstate)
+static void init_edsamstate(gmx_edsam * ed, edsamhistory_t *EDstate)
 {
     int      i, nr_edi;
     t_edpar *edi;
@@ -2446,7 +2472,7 @@ static void nice_legend_evec(const char ***setname, int *nsets, char **LegendStr
 
 
 /* Makes a legend for the xvg output file. Call on MASTER only! */
-static void write_edo_legend(gmx_edsam_t ed, int nED, const gmx_output_env_t *oenv)
+static void write_edo_legend(gmx_edsam * ed, int nED, const gmx_output_env_t *oenv)
 {
     t_edpar     *edi = nullptr;
     int          i;
@@ -2623,7 +2649,7 @@ static void write_edo_legend(gmx_edsam_t ed, int nED, const gmx_output_env_t *oe
 
 /* Init routine for ED and flooding. Calls init_edi in a loop for every .edi-cycle
  * contained in the input file, creates a NULL terminated list of t_edpar structures */
-gmx_edsam_t init_edsam(
+std::unique_ptr<gmx::EssentialDynamics> init_edsam(
         const char             *ediFileName,
         const char             *edoFileName,
         const gmx_mtop_t       *mtop,
@@ -2657,7 +2683,8 @@ gmx_edsam_t init_edsam(
     }
 
     /* Open input and output files, allocate space for ED data structure */
-    gmx_edsam_t ed = ed_open(mtop->natoms, oh, ediFileName, edoFileName, bAppend, oenv, cr);
+    auto edHandle = ed_open(mtop->natoms, oh, ediFileName, edoFileName, bAppend, oenv, cr);
+    auto ed       = edHandle->getLegacyED();
     GMX_RELEASE_ASSERT(constr != nullptr, "Must have valid constraints object");
     constr->saveEdsamPointer(ed);
 
@@ -2985,7 +3012,7 @@ gmx_edsam_t init_edsam(
         fflush(ed->edo);
     }
 
-    return ed;
+    return edHandle;
 }
 
 
@@ -2995,7 +3022,7 @@ void do_edsam(const t_inputrec *ir,
               rvec              xs[],
               rvec              v[],
               matrix            box,
-              gmx_edsam_t       ed)
+              gmx_edsam        *ed)
 {
     int                i, edinr, iupdate = 500;
     matrix             rotmat;         /* rotation matrix */
@@ -3170,16 +3197,3 @@ void do_edsam(const t_inputrec *ir,
 
     ed->bFirst = FALSE;
 }
-
-void done_ed(gmx_edsam_t *ed)
-{
-    if (*ed)
-    {
-        /* ed->edo is opened sometimes with xvgropen, sometimes with
-         * gmx_fio_fopen, so we use the least common denominator for
-         * closing. */
-        gmx_fio_fclose((*ed)->edo);
-    }
-
-    /* TODO deallocate ed and set pointer to NULL */
-}
index 8540a4d8e4d57cfa4adea2c41f741b46301c90f5..68f422c30b4db48a3124af594ba80ab226ed3948 100644 (file)
 #ifndef GMX_ESSENTIALDYNAMICS_EDSAM_H
 #define GMX_ESSENTIALDYNAMICS_EDSAM_H
 
+#include <memory>
+
 #include "gromacs/math/vectypes.h"
 #include "gromacs/utility/basedefinitions.h"
-
+#include "gromacs/utility/classhelpers.h"
 
 /*! \brief Abstract type for essential dynamics
  *
  * The main type is defined only in edsam.cpp
  */
-typedef struct gmx_edsam *gmx_edsam_t;
-
+struct gmx_edsam;
 struct gmx_domdec_t;
 struct gmx_mtop_t;
 struct gmx_output_env_t;
@@ -70,7 +71,23 @@ class t_state;
 namespace gmx
 {
 class Constraints;
-}
+class EssentialDynamics
+{
+    public:
+        EssentialDynamics();
+        ~EssentialDynamics();
+
+        /*! \brief Getter for working data
+         *
+         * This is needed while the module is still under
+         * construction. */
+        gmx_edsam *getLegacyED();
+    private:
+        class Impl;
+
+        PrivateImplPointer<Impl> impl_;
+};
+} // namespace gmx
 
 /*! \brief Applies essential dynamics constrains as defined in the .edi input file.
  *
@@ -101,7 +118,7 @@ void do_edsam(const t_inputrec *ir, int64_t step,
  *
  * \returns                 A pointer to the ED data structure.
  */
-gmx_edsam_t init_edsam(
+std::unique_ptr<gmx::EssentialDynamics> init_edsam(
         const char             *ediFileName,
         const char             *edoFileName,
         const gmx_mtop_t       *mtop,
@@ -120,7 +137,7 @@ gmx_edsam_t init_edsam(
  * \param dd                Domain decomposition data.
  * \param ed                Essential dynamics and flooding data.
  */
-void dd_make_local_ed_indices(gmx_domdec_t *dd, gmx_edsam_t ed);
+void dd_make_local_ed_indices(gmx_domdec_t *dd, gmx_edsam * ed);
 
 
 /*! \brief Evaluate the flooding potential(s) and forces as requested in the .edi input file.
@@ -143,10 +160,4 @@ void do_flood(const t_commrec  *cr,
               int64_t           step,
               gmx_bool          bNS);
 
-/*! \brief Clean up
- *
- * \param ed                The essential dynamics data
- */
-void done_ed(gmx_edsam_t *ed);
-
 #endif
index e6372aea547d6a51e7048defc7ac2d282c1c9f53..fd90a6ce82f4aa1459af9fd25c4313c4d9e50720 100644 (file)
@@ -153,7 +153,7 @@ class Constraints::Impl
         //! The number of warnings for SETTLE.
         int                   warncount_settle = 0;
         //! The essential dynamics data.
-        gmx_edsam_t           ed = nullptr;
+        gmx_edsam *           ed = nullptr;
 
         //! Thread-local virial contribution.
         tensor            *vir_r_m_dr_th = {nullptr};
@@ -1102,7 +1102,7 @@ Constraints::Impl::~Impl()
     done_lincs(lincsd);
 }
 
-void Constraints::saveEdsamPointer(gmx_edsam_t ed)
+void Constraints::saveEdsamPointer(gmx_edsam * ed)
 {
     impl_->ed = ed;
 }
index f7ebf89795f85ca4067b0183f7690cfa0b7b190c..70d2b430e883bc81e4fd92b3b9be38bd61bc8eba 100644 (file)
@@ -392,7 +392,7 @@ void gmx::Integrator::do_md()
     }
     groups = &top_global->groups;
 
-    gmx_edsam *ed = nullptr;
+    std::unique_ptr<EssentialDynamics> ed = nullptr;
     if (opt2bSet("-ei", nfile, fnm) || observablesHistory->edsamHistory != nullptr)
     {
         /* Initialize essential dynamics sampling */
@@ -1143,7 +1143,7 @@ void gmx::Integrator::do_md()
                      state->box, state->x, &state->hist,
                      f, force_vir, mdatoms, enerd, fcd,
                      state->lambda, graph,
-                     fr, vsite, mu_tot, t, ed,
+                     fr, vsite, mu_tot, t, ed ? ed->getLegacyED() : nullptr,
                      (bNS ? GMX_FORCE_NS : 0) | force_flags,
                      ddOpenBalanceRegion, ddCloseBalanceRegion);
         }
@@ -1923,9 +1923,6 @@ void gmx::Integrator::do_md()
         finish_swapcoords(ir->swap);
     }
 
-    /* Do essential dynamics cleanup if needed. Close .edo file */
-    done_ed(&ed);
-
     /* IMD cleanup, if bIMD is TRUE. */
     IMD_finalize(ir->bIMD, ir->imd);