Eliminate main.h
authorMark Abraham <mark.j.abraham@gmail.com>
Wed, 12 Sep 2018 13:46:38 +0000 (15:46 +0200)
committerPaul Bauer <paul.bauer.q@gmail.com>
Thu, 13 Sep 2018 07:53:52 +0000 (09:53 +0200)
This generic file had generic content and will create cyclic
dependencies if not broken up into logical units.

Moved replica exchange code to be alongside the multisim code that it
needs. Moved multi-sim communication routines to be where other
low-level and multi-sim communication routines are found. Added simple
Doxygen, while leaving a suppression and TODO for the main
replica-exchange routines documentation, which is not in scope for
this change. Converted a define to a constexpr and made the include
guards match GROMACS style.

Change-Id: I123231d56bfa9a699ddbd32fec0b055cf14d93e3

17 files changed:
src/gromacs/gmxlib/network.cpp
src/gromacs/gmxlib/network.h
src/gromacs/listed-forces/disre.cpp
src/gromacs/listed-forces/orires.cpp
src/gromacs/mdlib/main.cpp [deleted file]
src/gromacs/mdrun/CMakeLists.txt
src/gromacs/mdrun/logging.cpp [new file with mode: 0644]
src/gromacs/mdrun/logging.h [new file with mode: 0644]
src/gromacs/mdrun/md.cpp
src/gromacs/mdrun/multisim.cpp [new file with mode: 0644]
src/gromacs/mdrun/multisim.h [moved from src/gromacs/mdlib/main.h with 59% similarity]
src/gromacs/mdrun/replicaexchange.cpp [moved from src/gromacs/mdlib/repl_ex.cpp with 94% similarity]
src/gromacs/mdrun/replicaexchange.h [moved from src/gromacs/mdlib/repl_ex.h with 70% similarity]
src/gromacs/mdrun/runner.cpp
src/gromacs/mdrun/runner.h
src/gromacs/mdrunutility/handlerestart.cpp
src/programs/mdrun/mdrun.cpp

index c35e91ff99260157bb9d805c8f848bc628047b92..41f6826ba27bf1f53ccbc1081d473bdee8799f53 100644 (file)
@@ -639,6 +639,115 @@ void gmx_sumli_sim(int gmx_unused nr, int64_t gmx_unused r[], const gmx_multisim
 #endif
 }
 
+void check_multi_int(FILE *log, const gmx_multisim_t *ms, int val,
+                     const char *name,
+                     gmx_bool bQuiet)
+{
+    int     *ibuf, p;
+    gmx_bool bCompatible;
+
+    if (nullptr != log && !bQuiet)
+    {
+        fprintf(log, "Multi-checking %s ... ", name);
+    }
+
+    if (ms == nullptr)
+    {
+        gmx_fatal(FARGS,
+                  "check_multi_int called with a NULL communication pointer");
+    }
+
+    snew(ibuf, ms->nsim);
+    ibuf[ms->sim] = val;
+    gmx_sumi_sim(ms->nsim, ibuf, ms);
+
+    bCompatible = TRUE;
+    for (p = 1; p < ms->nsim; p++)
+    {
+        bCompatible = bCompatible && (ibuf[p-1] == ibuf[p]);
+    }
+
+    if (bCompatible)
+    {
+        if (nullptr != log && !bQuiet)
+        {
+            fprintf(log, "OK\n");
+        }
+    }
+    else
+    {
+        if (nullptr != log)
+        {
+            fprintf(log, "\n%s is not equal for all subsystems\n", name);
+            for (p = 0; p < ms->nsim; p++)
+            {
+                fprintf(log, "  subsystem %d: %d\n", p, ibuf[p]);
+            }
+        }
+        gmx_fatal(FARGS, "The %d subsystems are not compatible\n", ms->nsim);
+    }
+
+    sfree(ibuf);
+}
+
+void check_multi_int64(FILE *log, const gmx_multisim_t *ms,
+                       int64_t val, const char *name,
+                       gmx_bool bQuiet)
+{
+    int64_t          *ibuf;
+    int               p;
+    gmx_bool          bCompatible;
+
+    if (nullptr != log && !bQuiet)
+    {
+        fprintf(log, "Multi-checking %s ... ", name);
+    }
+
+    if (ms == nullptr)
+    {
+        gmx_fatal(FARGS,
+                  "check_multi_int called with a NULL communication pointer");
+    }
+
+    snew(ibuf, ms->nsim);
+    ibuf[ms->sim] = val;
+    gmx_sumli_sim(ms->nsim, ibuf, ms);
+
+    bCompatible = TRUE;
+    for (p = 1; p < ms->nsim; p++)
+    {
+        bCompatible = bCompatible && (ibuf[p-1] == ibuf[p]);
+    }
+
+    if (bCompatible)
+    {
+        if (nullptr != log && !bQuiet)
+        {
+            fprintf(log, "OK\n");
+        }
+    }
+    else
+    {
+        // TODO Part of this error message would also be good to go to
+        // stderr (from one rank of one sim only)
+        if (nullptr != log)
+        {
+            fprintf(log, "\n%s is not equal for all subsystems\n", name);
+            for (p = 0; p < ms->nsim; p++)
+            {
+                char strbuf[255];
+                /* first make the format string */
+                snprintf(strbuf, 255, "  subsystem %%d: %s\n",
+                         "%" PRId64);
+                fprintf(log, strbuf, p, ibuf[p]);
+            }
+        }
+        gmx_fatal(FARGS, "The %d subsystems are not compatible\n", ms->nsim);
+    }
+
+    sfree(ibuf);
+}
+
 const char *opt2fn_master(const char *opt, int nfile, const t_filenm fnm[],
                           t_commrec *cr)
 {
index 901d48a7c5db38b8644ab902745e9b0ad24a4414..233d64c46938a5b6e544be315fc0bfd5bcf2a4c2 100644 (file)
@@ -103,6 +103,18 @@ void gmx_sumf_sim(int nr, float r[], const struct gmx_multisim_t *ms);
 void gmx_sumd_sim(int nr, double r[], const struct gmx_multisim_t *ms);
 /* Calculate the sum over the simulations of an array of doubles */
 
+void check_multi_int(FILE *log, const gmx_multisim_t *ms,
+                     int val, const char *name,
+                     gmx_bool bQuiet);
+void check_multi_int64(FILE *log, const gmx_multisim_t *ms,
+                       int64_t val, const char *name,
+                       gmx_bool bQuiet);
+/* Check if val is the same on all processors for a mdrun -multidir run
+ * The string name is used to print to the log file and in a fatal error
+ * if the val's don't match. If bQuiet is true and the check passes,
+ * no output is written.
+ */
+
 #if GMX_DOUBLE
 #define gmx_sum       gmx_sumd
 #define gmx_sum_sim   gmx_sumd_sim
index 8d6bcb85c3239fa68ed88540c7aa10153b559b5c..a1b677fe5443bf93586df4f1ccaa7702c9521b96 100644 (file)
@@ -50,7 +50,6 @@
 #include "gromacs/gmxlib/network.h"
 #include "gromacs/math/functions.h"
 #include "gromacs/math/vec.h"
-#include "gromacs/mdlib/main.h"
 #include "gromacs/mdtypes/commrec.h"
 #include "gromacs/mdtypes/fcdata.h"
 #include "gromacs/mdtypes/inputrec.h"
index b7f9cfd04d14cc3a69687ccaa3578c6e9b03643a..90e4c9e0af30b17822a63fa0c16c0b9109ef15c2 100644 (file)
@@ -46,7 +46,6 @@
 #include "gromacs/math/do_fit.h"
 #include "gromacs/math/functions.h"
 #include "gromacs/math/vec.h"
-#include "gromacs/mdlib/main.h"
 #include "gromacs/mdtypes/commrec.h"
 #include "gromacs/mdtypes/fcdata.h"
 #include "gromacs/mdtypes/inputrec.h"
diff --git a/src/gromacs/mdlib/main.cpp b/src/gromacs/mdlib/main.cpp
deleted file mode 100644 (file)
index 92f24fc..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * This file is part of the GROMACS molecular simulation package.
- *
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017,2018, 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.
- *
- * GROMACS is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * GROMACS is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with GROMACS; if not, see
- * http://www.gnu.org/licenses, or write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
- *
- * If you want to redistribute modifications to GROMACS, please
- * consider that scientific software is very special. Version
- * control is crucial - bugs must be traceable. We will be happy to
- * consider code for inclusion in the official distribution, but
- * derived work must not be called official GROMACS. Details are found
- * in the README & COPYING files - if they are missing, get the
- * official version 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.
- */
-#include "gmxpre.h"
-
-#include "main.h"
-
-#include "config.h"
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-
-#include <string>
-
-#include "gromacs/commandline/filenm.h"
-#include "gromacs/fileio/gmxfio.h"
-#include "gromacs/gmxlib/network.h"
-#include "gromacs/mdtypes/commrec.h"
-#include "gromacs/utility/binaryinformation.h"
-#include "gromacs/utility/cstringutil.h"
-#include "gromacs/utility/exceptions.h"
-#include "gromacs/utility/fatalerror.h"
-#include "gromacs/utility/futil.h"
-#include "gromacs/utility/gmxassert.h"
-#include "gromacs/utility/gmxmpi.h"
-#include "gromacs/utility/path.h"
-#include "gromacs/utility/programcontext.h"
-#include "gromacs/utility/smalloc.h"
-#include "gromacs/utility/snprintf.h"
-#include "gromacs/utility/stringutil.h"
-#include "gromacs/utility/sysinfo.h"
-
-/* The source code in this file should be thread-safe.
-         Please keep it that way. */
-
-// TODO move this to multi-sim module
-void check_multi_int(FILE *log, const gmx_multisim_t *ms, int val,
-                     const char *name,
-                     gmx_bool bQuiet)
-{
-    int     *ibuf, p;
-    gmx_bool bCompatible;
-
-    if (nullptr != log && !bQuiet)
-    {
-        fprintf(log, "Multi-checking %s ... ", name);
-    }
-
-    if (ms == nullptr)
-    {
-        gmx_fatal(FARGS,
-                  "check_multi_int called with a NULL communication pointer");
-    }
-
-    snew(ibuf, ms->nsim);
-    ibuf[ms->sim] = val;
-    gmx_sumi_sim(ms->nsim, ibuf, ms);
-
-    bCompatible = TRUE;
-    for (p = 1; p < ms->nsim; p++)
-    {
-        bCompatible = bCompatible && (ibuf[p-1] == ibuf[p]);
-    }
-
-    if (bCompatible)
-    {
-        if (nullptr != log && !bQuiet)
-        {
-            fprintf(log, "OK\n");
-        }
-    }
-    else
-    {
-        if (nullptr != log)
-        {
-            fprintf(log, "\n%s is not equal for all subsystems\n", name);
-            for (p = 0; p < ms->nsim; p++)
-            {
-                fprintf(log, "  subsystem %d: %d\n", p, ibuf[p]);
-            }
-        }
-        gmx_fatal(FARGS, "The %d subsystems are not compatible\n", ms->nsim);
-    }
-
-    sfree(ibuf);
-}
-
-// TODO move this to multi-sim module
-void check_multi_int64(FILE *log, const gmx_multisim_t *ms,
-                       int64_t val, const char *name,
-                       gmx_bool bQuiet)
-{
-    int64_t          *ibuf;
-    int               p;
-    gmx_bool          bCompatible;
-
-    if (nullptr != log && !bQuiet)
-    {
-        fprintf(log, "Multi-checking %s ... ", name);
-    }
-
-    if (ms == nullptr)
-    {
-        gmx_fatal(FARGS,
-                  "check_multi_int called with a NULL communication pointer");
-    }
-
-    snew(ibuf, ms->nsim);
-    ibuf[ms->sim] = val;
-    gmx_sumli_sim(ms->nsim, ibuf, ms);
-
-    bCompatible = TRUE;
-    for (p = 1; p < ms->nsim; p++)
-    {
-        bCompatible = bCompatible && (ibuf[p-1] == ibuf[p]);
-    }
-
-    if (bCompatible)
-    {
-        if (nullptr != log && !bQuiet)
-        {
-            fprintf(log, "OK\n");
-        }
-    }
-    else
-    {
-        // TODO Part of this error message would also be good to go to
-        // stderr (from one rank of one sim only)
-        if (nullptr != log)
-        {
-            fprintf(log, "\n%s is not equal for all subsystems\n", name);
-            for (p = 0; p < ms->nsim; p++)
-            {
-                char strbuf[255];
-                /* first make the format string */
-                snprintf(strbuf, 255, "  subsystem %%d: %s\n",
-                         "%" PRId64);
-                fprintf(log, strbuf, p, ibuf[p]);
-            }
-        }
-        gmx_fatal(FARGS, "The %d subsystems are not compatible\n", ms->nsim);
-    }
-
-    sfree(ibuf);
-}
-
-
-void gmx_log_open(const char *lognm, const t_commrec *cr,
-                  gmx_bool bAppendFiles, FILE** fplog)
-{
-    int    pid;
-    char   host[256];
-    char   timebuf[STRLEN];
-    FILE  *fp = *fplog;
-
-    if (!bAppendFiles)
-    {
-        fp = gmx_fio_fopen(lognm, bAppendFiles ? "a+" : "w+" );
-    }
-
-    gmx_fatal_set_log_file(fp);
-
-    /* Get some machine parameters */
-    gmx_gethostname(host, 256);
-    pid = gmx_getpid();
-    gmx_format_current_time(timebuf, STRLEN);
-
-    if (bAppendFiles)
-    {
-        fprintf(fp,
-                "\n"
-                "\n"
-                "-----------------------------------------------------------\n"
-                "Restarting from checkpoint, appending to previous log file.\n"
-                "\n"
-                );
-    }
-
-    fprintf(fp,
-            "Log file opened on %s"
-            "Host: %s  pid: %d  rank ID: %d  number of ranks:  %d\n",
-            timebuf, host, pid, cr->nodeid, cr->nnodes);
-    try
-    {
-        gmx::BinaryInformationSettings settings;
-        settings.extendedInfo(true);
-        settings.copyright(!bAppendFiles);
-        gmx::printBinaryInformation(fp, gmx::getProgramContext(), settings);
-    }
-    GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
-    fprintf(fp, "\n");
-
-    fflush(fp);
-
-    *fplog = fp;
-}
-
-void gmx_log_close(FILE *fp)
-{
-    if (fp)
-    {
-        gmx_fatal_set_log_file(nullptr);
-        gmx_fio_fclose(fp);
-    }
-}
-
-// TODO move this to multi-sim module
-gmx_multisim_t *init_multisystem(MPI_Comm                         comm,
-                                 gmx::ArrayRef<const std::string> multidirs)
-{
-    gmx_multisim_t *ms;
-#if GMX_MPI
-    MPI_Group       mpi_group_world;
-    int            *rank;
-#endif
-
-    if (multidirs.empty())
-    {
-        return nullptr;
-    }
-
-    if (!GMX_LIB_MPI && !multidirs.empty())
-    {
-        gmx_fatal(FARGS, "mdrun -multidir is only supported when GROMACS has been "
-                  "configured with a proper external MPI library.");
-    }
-
-    if (multidirs.size() == 1)
-    {
-        /* NOTE: It would be nice if this special case worked, but this requires checks/tests. */
-        gmx_fatal(FARGS, "To run mdrun in multiple simulation mode, more then one "
-                  "actual simulation is required. The single simulation case is not supported.");
-    }
-
-#if GMX_MPI
-    int numRanks;
-    MPI_Comm_size(comm, &numRanks);
-    if (numRanks % multidirs.size() != 0)
-    {
-        gmx_fatal(FARGS, "The number of ranks (%d) is not a multiple of the number of simulations (%td)", numRanks, multidirs.size());
-    }
-
-    int numRanksPerSim = numRanks/multidirs.size();
-    int rankWithinComm;
-    MPI_Comm_rank(comm, &rankWithinComm);
-
-    if (debug)
-    {
-        fprintf(debug, "We have %td simulations, %d ranks per simulation, local simulation is %d\n", multidirs.size(), numRanksPerSim, rankWithinComm/numRanksPerSim);
-    }
-
-    ms       = new gmx_multisim_t;
-    ms->nsim = multidirs.size();
-    ms->sim  = rankWithinComm/numRanksPerSim;
-    /* Create a communicator for the master nodes */
-    snew(rank, ms->nsim);
-    for (int i = 0; i < ms->nsim; i++)
-    {
-        rank[i] = i*numRanksPerSim;
-    }
-    MPI_Comm_group(comm, &mpi_group_world);
-    MPI_Group_incl(mpi_group_world, ms->nsim, rank, &ms->mpi_group_masters);
-    sfree(rank);
-    MPI_Comm_create(MPI_COMM_WORLD, ms->mpi_group_masters,
-                    &ms->mpi_comm_masters);
-
-#if !MPI_IN_PLACE_EXISTS
-    /* initialize the MPI_IN_PLACE replacement buffers */
-    snew(ms->mpb, 1);
-    ms->mpb->ibuf        = NULL;
-    ms->mpb->libuf       = NULL;
-    ms->mpb->fbuf        = NULL;
-    ms->mpb->dbuf        = NULL;
-    ms->mpb->ibuf_alloc  = 0;
-    ms->mpb->libuf_alloc = 0;
-    ms->mpb->fbuf_alloc  = 0;
-    ms->mpb->dbuf_alloc  = 0;
-#endif
-
-    // TODO This should throw upon error
-    gmx_chdir(multidirs[ms->sim].c_str());
-#else
-    GMX_UNUSED_VALUE(comm);
-    ms = nullptr;
-#endif
-
-    return ms;
-}
-
-void done_multisim(gmx_multisim_t *ms)
-{
-    if (nullptr != ms)
-    {
-        done_mpi_in_place_buf(ms->mpb);
-        delete ms;
-    }
-}
index 3b3b9b3f156a44e74c6799eaf60dbd6d86ce800d..430c4d77567c50cc20b1c4860efe9314f96f9d6d 100644 (file)
 
 gmx_add_libgromacs_sources(
     integrator.cpp
+    logging.cpp
     md.cpp
     minimize.cpp
+    multisim.cpp
+    replicaexchange.cpp
     runner.cpp
     tpi.cpp
     )
diff --git a/src/gromacs/mdrun/logging.cpp b/src/gromacs/mdrun/logging.cpp
new file mode 100644 (file)
index 0000000..b1707c0
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2018, 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.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version 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.
+ */
+/*! \internal \file
+ *
+ * \brief Implements the MD log file handling routines.
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_mdrun
+ */
+#include "gmxpre.h"
+
+#include "logging.h"
+
+#include "gromacs/fileio/gmxfio.h"
+#include "gromacs/mdtypes/commrec.h"
+#include "gromacs/utility/binaryinformation.h"
+#include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/programcontext.h"
+#include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/sysinfo.h"
+
+void gmx_log_open(const char *lognm, const t_commrec *cr,
+                  gmx_bool bAppendFiles, FILE** fplog)
+{
+    int    pid;
+    char   host[256];
+    char   timebuf[STRLEN];
+    FILE  *fp = *fplog;
+
+    if (!bAppendFiles)
+    {
+        fp = gmx_fio_fopen(lognm, bAppendFiles ? "a+" : "w+" );
+    }
+
+    gmx_fatal_set_log_file(fp);
+
+    /* Get some machine parameters */
+    gmx_gethostname(host, 256);
+    pid = gmx_getpid();
+    gmx_format_current_time(timebuf, STRLEN);
+
+    if (bAppendFiles)
+    {
+        fprintf(fp,
+                "\n"
+                "\n"
+                "-----------------------------------------------------------\n"
+                "Restarting from checkpoint, appending to previous log file.\n"
+                "\n"
+                );
+    }
+
+    fprintf(fp,
+            "Log file opened on %s"
+            "Host: %s  pid: %d  rank ID: %d  number of ranks:  %d\n",
+            timebuf, host, pid, cr->nodeid, cr->nnodes);
+    try
+    {
+        gmx::BinaryInformationSettings settings;
+        settings.extendedInfo(true);
+        settings.copyright(!bAppendFiles);
+        gmx::printBinaryInformation(fp, gmx::getProgramContext(), settings);
+    }
+    GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
+    fprintf(fp, "\n");
+
+    fflush(fp);
+
+    *fplog = fp;
+}
+
+void gmx_log_close(FILE *fp)
+{
+    if (fp)
+    {
+        gmx_fatal_set_log_file(nullptr);
+        gmx_fio_fclose(fp);
+    }
+}
diff --git a/src/gromacs/mdrun/logging.h b/src/gromacs/mdrun/logging.h
new file mode 100644 (file)
index 0000000..9d9a274
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2018, 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.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version 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 Declares the MD log file handling routines.
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \inlibraryapi
+ * \ingroup module_mdrun
+ */
+#ifndef GMX_MDRUN_LOGGING_H
+#define GMX_MDRUN_LOGGING_H
+
+#include <cstdio>
+
+#include "gromacs/utility/basedefinitions.h"
+
+struct gmx_multisim_t;
+struct t_commrec;
+
+/*! \brief Open the log file */
+void gmx_log_open(const char *fn, const t_commrec *cr,
+                  gmx_bool bAppendFiles, FILE** /*fplog*/);
+
+/*! \brief Close the log file */
+void gmx_log_close(FILE *fp);
+
+#endif
index 7e05cac6d6c533caeca472693401271b67afbf07..05daa4b60a78cb890ede6f9b61d081ce69b53d2a 100644 (file)
@@ -89,7 +89,6 @@
 #include "gromacs/mdlib/nb_verlet.h"
 #include "gromacs/mdlib/nbnxn_gpu_data_mgmt.h"
 #include "gromacs/mdlib/ns.h"
-#include "gromacs/mdlib/repl_ex.h"
 #include "gromacs/mdlib/shellfc.h"
 #include "gromacs/mdlib/sighandler.h"
 #include "gromacs/mdlib/sim_util.h"
 #include "gromacs/utility/smalloc.h"
 
 #include "integrator.h"
+#include "replicaexchange.h"
 
 #ifdef GMX_FAHCORE
 #include "corewrap.h"
diff --git a/src/gromacs/mdrun/multisim.cpp b/src/gromacs/mdrun/multisim.cpp
new file mode 100644 (file)
index 0000000..b3a73ee
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2018, 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.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version 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.
+ */
+/*! \internal \file
+ *
+ * \brief Implements the multi-simulation support routines.
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_mdrun
+ */
+#include "gmxpre.h"
+
+#include "multisim.h"
+
+#include "config.h"
+
+#include "gromacs/gmxlib/network.h"
+#include "gromacs/mdtypes/commrec.h"
+#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/futil.h"
+#include "gromacs/utility/smalloc.h"
+
+gmx_multisim_t *init_multisystem(MPI_Comm                         comm,
+                                 gmx::ArrayRef<const std::string> multidirs)
+{
+    gmx_multisim_t *ms;
+#if GMX_MPI
+    MPI_Group       mpi_group_world;
+    int            *rank;
+#endif
+
+    if (multidirs.empty())
+    {
+        return nullptr;
+    }
+
+    if (!GMX_LIB_MPI && !multidirs.empty())
+    {
+        gmx_fatal(FARGS, "mdrun -multidir is only supported when GROMACS has been "
+                  "configured with a proper external MPI library.");
+    }
+
+    if (multidirs.size() == 1)
+    {
+        /* NOTE: It would be nice if this special case worked, but this requires checks/tests. */
+        gmx_fatal(FARGS, "To run mdrun in multiple simulation mode, more then one "
+                  "actual simulation is required. The single simulation case is not supported.");
+    }
+
+#if GMX_MPI
+    int numRanks;
+    MPI_Comm_size(comm, &numRanks);
+    if (numRanks % multidirs.size() != 0)
+    {
+        gmx_fatal(FARGS, "The number of ranks (%d) is not a multiple of the number of simulations (%td)", numRanks, multidirs.size());
+    }
+
+    int numRanksPerSim = numRanks/multidirs.size();
+    int rankWithinComm;
+    MPI_Comm_rank(comm, &rankWithinComm);
+
+    if (debug)
+    {
+        fprintf(debug, "We have %td simulations, %d ranks per simulation, local simulation is %d\n", multidirs.size(), numRanksPerSim, rankWithinComm/numRanksPerSim);
+    }
+
+    ms       = new gmx_multisim_t;
+    ms->nsim = multidirs.size();
+    ms->sim  = rankWithinComm/numRanksPerSim;
+    /* Create a communicator for the master nodes */
+    snew(rank, ms->nsim);
+    for (int i = 0; i < ms->nsim; i++)
+    {
+        rank[i] = i*numRanksPerSim;
+    }
+    MPI_Comm_group(comm, &mpi_group_world);
+    MPI_Group_incl(mpi_group_world, ms->nsim, rank, &ms->mpi_group_masters);
+    sfree(rank);
+    MPI_Comm_create(MPI_COMM_WORLD, ms->mpi_group_masters,
+                    &ms->mpi_comm_masters);
+
+#if !MPI_IN_PLACE_EXISTS
+    /* initialize the MPI_IN_PLACE replacement buffers */
+    snew(ms->mpb, 1);
+    ms->mpb->ibuf        = NULL;
+    ms->mpb->libuf       = NULL;
+    ms->mpb->fbuf        = NULL;
+    ms->mpb->dbuf        = NULL;
+    ms->mpb->ibuf_alloc  = 0;
+    ms->mpb->libuf_alloc = 0;
+    ms->mpb->fbuf_alloc  = 0;
+    ms->mpb->dbuf_alloc  = 0;
+#endif
+
+    // TODO This should throw upon error
+    gmx_chdir(multidirs[ms->sim].c_str());
+#else
+    GMX_UNUSED_VALUE(comm);
+    ms = nullptr;
+#endif
+
+    return ms;
+}
+
+void done_multisim(gmx_multisim_t *ms)
+{
+    if (nullptr != ms)
+    {
+        done_mpi_in_place_buf(ms->mpb);
+        delete ms;
+    }
+}
similarity index 59%
rename from src/gromacs/mdlib/main.h
rename to src/gromacs/mdrun/multisim.h
index 8c575693b121b59a1befb1db86e6ecf94da6f3b6..41b51459dff9351ae38e5edac8606eadf3b6095e 100644 (file)
@@ -1,9 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2018, by the GROMACS development team, led by
+ * Copyright (c) 2018, 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.
  */
-#ifndef GMX_MDLIB_MAIN_H
-#define GMX_MDLIB_MAIN_H
-
-#include <cstdio>
+/*! \libinternal \file
+ *
+ * \brief Declares the multi-simulation support routines.
+ *
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \inlibraryapi
+ * \ingroup module_mdrun
+ */
+#ifndef GMX_MDRUN_MULTISIM_H
+#define GMX_MDRUN_MULTISIM_H
 
 #include <string>
-#include <vector>
 
 #include "gromacs/utility/arrayref.h"
-#include "gromacs/utility/basedefinitions.h"
 #include "gromacs/utility/gmxmpi.h"
 
 struct gmx_multisim_t;
-struct t_commrec;
-struct t_filenm;
-
-void gmx_log_open(const char *fn, const t_commrec *cr,
-                  gmx_bool bAppendFiles, FILE** /*fplog*/);
-/* Open the log file, if necessary (nprocs > 1) the logfile name is
- * communicated around the ring.
- */
-
-void gmx_log_close(FILE *fp);
-/* Close the log file */
-
-void check_multi_int(FILE *log, const gmx_multisim_t *ms,
-                     int val, const char *name,
-                     gmx_bool bQuiet);
-void check_multi_int64(FILE *log, const gmx_multisim_t *ms,
-                       int64_t val, const char *name,
-                       gmx_bool bQuiet);
-/* Check if val is the same on all processors for a mdrun -multidir run
- * The string name is used to print to the log file and in a fatal error
- * if the val's don't match. If bQuiet is true and the check passes,
- * no output is written.
- */
 
+/*! \brief Initializes multi-simulations.
+ *
+ * Splits the communication into multidirs.size() separate
+ * simulations, if >1, and creates a communication structure between
+ * the master these simulations. */
 gmx_multisim_t *init_multisystem(MPI_Comm                         comm,
                                  gmx::ArrayRef<const std::string> multidirs);
-/* Splits the communication into multidirs.size() separate simulations, if >1,
- * and creates a communication structure between the master
- * these simulations.
- */
 
 //! Cleans up multi-system handler.
 void done_multisim(gmx_multisim_t *ms);
similarity index 94%
rename from src/gromacs/mdlib/repl_ex.cpp
rename to src/gromacs/mdrun/replicaexchange.cpp
index ce2021eb70f09dbc502c5c2dba51b3bea08f349a..87a5660147fda202c689a291ee4019a463b3127c 100644 (file)
  * the research papers on the package. Check out http://www.gromacs.org.
  */
 
+/*! \internal \file
+ *
+ * \brief Implements the replica exchange routines.
+ *
+ * \author David van der Spoel <david.vanderspoel@icm.uu.se>
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ * \ingroup module_mdrun
+ */
 #include "gmxpre.h"
 
-#include "repl_ex.h"
+#include "replicaexchange.h"
 
 #include "config.h"
 
@@ -49,7 +57,7 @@
 #include "gromacs/gmxlib/network.h"
 #include "gromacs/math/units.h"
 #include "gromacs/math/vec.h"
-#include "gromacs/mdlib/main.h"
+#include "gromacs/mdrun/multisim.h"
 #include "gromacs/mdtypes/commrec.h"
 #include "gromacs/mdtypes/enerdata.h"
 #include "gromacs/mdtypes/inputrec.h"
 #include "gromacs/utility/pleasecite.h"
 #include "gromacs/utility/smalloc.h"
 
+//! Helps cut off probability values.
+constexpr int c_probabilityCutoff = 100;
 
-#define PROBABILITYCUTOFF 100
 /* we don't bother evaluating if events are more rare than exp(-100) = 3.7x10^-44 */
 
-//! Rank in the multisimulaiton
+//! Rank in the multisimulation
 #define MSRANK(ms, nodeid)  (nodeid)
 
+//! Enum for replica exchange flavours
 enum {
     ereTEMP, ereLAMBDA, ereENDSINGLE, ereTL, ereNR
 };
+/*! \brief Strings describing replica exchange flavours.
+ *
+ *  end_single_marker merely notes the end of single variable replica
+ *  exchange. All types higher than it are multiple replica exchange
+ *  methods.
+ *
+ * Eventually, should add 'pressure', 'temperature and pressure',
+ *  'lambda_and_pressure', 'temperature_lambda_pressure'?; Let's wait
+ *  until we feel better about the pressure control methods giving
+ *  exact ensembles.  Right now, we assume constant pressure */
 static const char *erename[ereNR] = { "temperature", "lambda", "end_single_marker", "temperature and lambda"};
-/* end_single_marker merely notes the end of single variable replica exchange. All types higher than
-   it are multiple replica exchange methods */
-/* Eventually, should add 'pressure', 'temperature and pressure', 'lambda_and_pressure', 'temperature_lambda_pressure'?;
-   Let's wait until we feel better about the pressure control methods giving exact ensembles.  Right now, we assume constant pressure  */
 
-typedef struct gmx_repl_ex
+//! Working data for replica exchange.
+struct gmx_repl_ex
 {
-    int       repl;        /* replica ID */
-    int       nrepl;       /* total number of replica */
-    real      temp;        /* temperature */
-    int       type;        /* replica exchange type from ere enum */
-    real    **q;           /* quantity, e.g. temperature or lambda; first index is ere, second index is replica ID */
-    gmx_bool  bNPT;        /* use constant pressure and temperature */
-    real     *pres;        /* replica pressures */
-    int      *ind;         /* replica indices */
-    int      *allswaps;    /* used for keeping track of all the replica swaps */
-    int       nst;         /* replica exchange interval (number of steps) */
-    int       nex;         /* number of exchanges per interval */
-    int       seed;        /* random seed */
-    int       nattempt[2]; /* number of even and odd replica change attempts */
-    real     *prob_sum;    /* sum of probabilities */
-    int     **nmoves;      /* number of moves between replicas i and j */
-    int      *nexchange;   /* i-th element of the array is the number of exchanges between replica i-1 and i */
-
-    /* these are helper arrays for replica exchange; allocated here so they
-       don't have to be allocated each time */
+    //! Replica ID
+    int       repl;
+    //! Total number of replica
+    int       nrepl;
+    //! Temperature
+    real      temp;
+    //! Replica exchange type from ere enum
+    int       type;
+    //! Quantity, e.g. temperature or lambda; first index is ere, second index is replica ID
+    real    **q;
+    //! Use constant pressure and temperature
+    gmx_bool  bNPT;
+    //! Replica pressures
+    real     *pres;
+    //! Replica indices
+    int      *ind;
+    //! Used for keeping track of all the replica swaps
+    int      *allswaps;
+    //! Replica exchange interval (number of steps)
+    int       nst;
+    //! Number of exchanges per interval
+    int       nex;
+    //! Random seed
+    int       seed;
+    //! Number of even and odd replica change attempts
+    int       nattempt[2];
+    //! Sum of probabilities
+    real     *prob_sum;
+    //! Number of moves between replicas i and j
+    int     **nmoves;
+    //! i-th element of the array is the number of exchanges between replica i-1 and i
+    int      *nexchange;
+
+    /*! \brief Helper arrays for replica exchange; allocated here
+     * so they don't have to be allocated each time */
+    //! \{
     int      *destinations;
     int     **cyclic;
     int     **order;
     int      *tmpswap;
     gmx_bool *incycle;
     gmx_bool *bEx;
+    //! \}
 
-    /* helper arrays to hold the quantities that are exchanged */
+    //! Helper arrays to hold the quantities that are exchanged.
+    //! \{
     real  *prob;
     real  *Epot;
     real  *beta;
     real  *Vol;
     real **de;
+    //! \}
+};
 
-} t_gmx_repl_ex;
+// TODO We should add Doxygen here some time.
+//! \cond
 
 static gmx_bool repl_quantity(const gmx_multisim_t *ms,
                               struct gmx_repl_ex *re, int ere, real q)
@@ -946,7 +985,7 @@ test_for_replica_exchange(FILE                 *fplog,
             }
             else
             {
-                if (delta > PROBABILITYCUTOFF)
+                if (delta > c_probabilityCutoff)
                 {
                     prob[0] = 0;
                 }
@@ -995,7 +1034,7 @@ test_for_replica_exchange(FILE                 *fplog,
                 }
                 else
                 {
-                    if (delta > PROBABILITYCUTOFF)
+                    if (delta > c_probabilityCutoff)
                     {
                         prob[i] = 0;
                     }
@@ -1344,3 +1383,5 @@ void print_replica_exchange_statistics(FILE *fplog, struct gmx_repl_ex *re)
     /* print the transition matrix */
     print_transition_matrix(fplog, re->nrepl, re->nmoves, re->nattempt);
 }
+
+//! \endcond
similarity index 70%
rename from src/gromacs/mdlib/repl_ex.h
rename to src/gromacs/mdrun/replicaexchange.h
index 0f3b0202391d15360aea1ab07b146d3549c29257..3120e3873fedc5a712be5715d094d3b2de2d73da 100644 (file)
  * To help us fund GROMACS development, we humbly ask that you cite
  * the research papers on the package. Check out http://www.gromacs.org.
  */
-
-#ifndef _repl_ex_h
-#define _repl_ex_h
+/*! \libinternal \file
+ *
+ * \brief Declares the routines for replica exchange.
+ *
+ * \author David van der Spoel <david.vanderspoel@icm.uu.se>
+ * \author Mark Abraham <mark.j.abraham@gmail.com>
+ *
+ * \ingroup module_mdrun
+ */
+#ifndef GMX_MDRUN_REPLICAEXCHANGE_H
+#define GMX_MDRUN_REPLICAEXCHANGE_H
 
 #include <cstdio>
 
@@ -49,7 +57,8 @@ struct t_commrec;
 struct t_inputrec;
 class t_state;
 
-/* The parameters for the replica exchange algorithm */
+/*! \libinternal
+ * \brief The parameters for the replica exchange algorithm. */
 struct ReplicaExchangeParameters
 {
     ReplicaExchangeParameters() :
@@ -59,22 +68,37 @@ struct ReplicaExchangeParameters
     {
     }
 
-    int exchangeInterval; /* Interval in steps at which to attempt exchanges, 0 means no replica exchange */
-    int numExchanges;     /* The number of exchanges to attempt at an exchange step */
-    int randomSeed;       /* The random seed, -1 means generate a seed */
+    //! Interval in steps at which to attempt exchanges, 0 means no replica exchange.
+    int exchangeInterval;
+    //! The number of exchanges to attempt at an exchange step.
+    int numExchanges;
+    //! The random seed, -1 means generate a seed.
+    int randomSeed;
 };
 
-/* Abstract type for replica exchange */
+//! Abstract type for replica exchange
 typedef struct gmx_repl_ex *gmx_repl_ex_t;
 
+/*! \brief Setup function.
+ *
+ * Should only be called on the master ranks */
 gmx_repl_ex_t
 init_replica_exchange(FILE                            *fplog,
                       const gmx_multisim_t            *ms,
                       int                              numAtomsInSystem,
                       const t_inputrec                *ir,
                       const ReplicaExchangeParameters &replExParams);
-/* Should only be called on the master ranks */
 
+/*! \brief Attempts replica exchange.
+ *
+ * Should be called on all ranks.  When running each replica in
+ * parallel, this routine collects the state on the master rank before
+ * exchange.  With domain decomposition, the global state after
+ * exchange is stored in state and still needs to be redistributed
+ * over the ranks.
+ *
+ * \returns TRUE if the state has been exchanged.
+ */
 gmx_bool replica_exchange(FILE *fplog,
                           const t_commrec *cr,
                           const gmx_multisim_t *ms,
@@ -82,15 +106,10 @@ gmx_bool replica_exchange(FILE *fplog,
                           t_state *state, const gmx_enerdata_t *enerd,
                           t_state *state_local,
                           int64_t step, real time);
-/* Attempts replica exchange, should be called on all ranks.
- * Returns TRUE if this state has been exchanged.
- * When running each replica in parallel,
- * this routine collects the state on the master rank before exchange.
- * With domain decomposition, the global state after exchange is stored
- * in state and still needs to be redistributed over the ranks.
- */
 
+/*! \brief Prints replica exchange statistics to the log file.
+ *
+ * Should only be called on the master ranks */
 void print_replica_exchange_statistics(FILE *fplog, gmx_repl_ex_t re);
-/* Should only be called on the master ranks */
 
-#endif  /* _repl_ex_h */
+#endif
index 7337df0886251b4c24d86a565cd26ba2edae96a4..725857f909904f935e3439aad600d02372b091df 100644 (file)
@@ -81,7 +81,6 @@
 #include "gromacs/mdlib/calc_verletbuf.h"
 #include "gromacs/mdlib/forcerec.h"
 #include "gromacs/mdlib/gmx_omp_nthreads.h"
-#include "gromacs/mdlib/main.h"
 #include "gromacs/mdlib/makeconstraints.h"
 #include "gromacs/mdlib/md_support.h"
 #include "gromacs/mdlib/mdatoms.h"
 #include "gromacs/mdlib/nbnxn_search.h"
 #include "gromacs/mdlib/nbnxn_tuning.h"
 #include "gromacs/mdlib/qmmm.h"
-#include "gromacs/mdlib/repl_ex.h"
 #include "gromacs/mdlib/sighandler.h"
 #include "gromacs/mdlib/sim_util.h"
+#include "gromacs/mdrun/logging.h"
+#include "gromacs/mdrun/multisim.h"
 #include "gromacs/mdrunutility/mdmodules.h"
 #include "gromacs/mdrunutility/threadaffinity.h"
 #include "gromacs/mdtypes/commrec.h"
 #include "gromacs/utility/stringutil.h"
 
 #include "integrator.h"
+#include "replicaexchange.h"
 
 #ifdef GMX_FAHCORE
 #include "corewrap.h"
index 2789ff9500dd9d5f5efaf948f72ce77a87dfcf84..76613c61016b26990b525d3915b64e7e84681d88 100644 (file)
 #include "gromacs/hardware/hw_info.h"
 #include "gromacs/math/vec.h"
 #include "gromacs/mdlib/mdrun.h"
-#include "gromacs/mdlib/repl_ex.h"
 #include "gromacs/utility/basedefinitions.h"
 #include "gromacs/utility/real.h"
 
+#include "replicaexchange.h"
+
 struct gmx_output_env_t;
 struct ReplicaExchangeParameters;
 struct t_commrec;
index d710abdca603add1cb3f7f26b8b6e3d6c5c40707..be922b2fc552ff80ac189b64ba5791d1a04fe177 100644 (file)
@@ -57,7 +57,6 @@
 #include "gromacs/fileio/checkpoint.h"
 #include "gromacs/fileio/gmxfio.h"
 #include "gromacs/gmxlib/network.h"
-#include "gromacs/mdlib/main.h"
 #include "gromacs/mdtypes/commrec.h"
 #include "gromacs/utility/basedefinitions.h"
 #include "gromacs/utility/fatalerror.h"
index 651b97a4c2614638b6f8686679c2da2001e3cafa..70238226404538da7e6620cb009fd203528d0b86 100644 (file)
 #include "gromacs/commandline/pargs.h"
 #include "gromacs/domdec/domdec.h"
 #include "gromacs/gmxlib/network.h"
-#include "gromacs/mdlib/main.h"
 #include "gromacs/mdlib/mdrun.h"
-#include "gromacs/mdlib/repl_ex.h"
+#include "gromacs/mdrun/logging.h"
+#include "gromacs/mdrun/multisim.h"
+#include "gromacs/mdrun/replicaexchange.h"
 #include "gromacs/mdrun/runner.h"
 #include "gromacs/mdrunutility/handlerestart.h"
 #include "gromacs/mdtypes/commrec.h"