Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / utility / init.cpp
index 2c34d946a203f2e1ce1d85930a513bc418f3df5d..f2110535746b66991231117ba7577eeed875a686 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2013, by the GROMACS development team, led by
- * David van der Spoel, Berk Hess, Erik Lindahl, and including many
- * others, as listed in the AUTHORS file in the top-level source
- * directory and at http://www.gromacs.org.
+ * Copyright (c) 2013,2014, 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
  * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \ingroup module_utility
  */
-#include "gromacs/utility/init.h"
+#include "gmxpre.h"
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "init.h"
 
-#include <cstring>
+#include "config.h"
 
 #ifdef GMX_LIB_MPI
 #include "gromacs/utility/gmxmpi.h"
 #endif
 
-#include "gromacs/legacyheaders/network.h"
-#include "gromacs/legacyheaders/smalloc.h"
-#include "gromacs/legacyheaders/types/commrec.h"
-
-#include "gromacs/utility/programinfo.h"
+#include "gromacs/utility/common.h"
+#include "gromacs/utility/gmxassert.h"
 
 namespace gmx
 {
 
-#ifdef GMX_LIB_MPI
 namespace
 {
+#ifdef GMX_LIB_MPI
+//! Maintains global counter of attempts to initialize MPI
+int g_initializationCounter = 0;
+#endif
+}
 
-void broadcastArguments(const t_commrec *cr, int *argc, char ***argv)
+void init(int *argc, char ***argv)
 {
-    gmx_bcast(sizeof(*argc), argc, cr);
-
-    if (!MASTER(cr))
-    {
-        snew(*argv, *argc+1);
-    }
-    for (int i = 0; i < *argc; i++)
+#ifdef GMX_LIB_MPI
+    int isInitialized = 0, isFinalized = 0;
+    MPI_Finalized(&isFinalized);
+    GMX_RELEASE_ASSERT(!isFinalized, "Invalid attempt to initialize MPI after finalization");
+    MPI_Initialized(&isInitialized);
+    if (isInitialized)
     {
-        int len;
-        if (MASTER(cr))
+        if (0 == g_initializationCounter)
         {
-            len = std::strlen((*argv)[i])+1;
+            // Some other code has already initialized MPI, so bump the counter so that
+            // we know not to finalize MPI ourselves later.
+            g_initializationCounter++;
         }
-        gmx_bcast(sizeof(len), &len, cr);
-        if (!MASTER(cr))
-        {
-            snew((*argv)[i], len);
-        }
-        gmx_bcast(len, (*argv)[i], cr);
     }
-}
+    else
+    {
+#ifdef GMX_FAHCORE
+        (void) fah_MPI_Init(argc, argv);
+#else
+        (void) MPI_Init(argc, argv);
+#endif
+    }
+    // Bump the counter to record this initialization event
+    g_initializationCounter++;
 
-} // namespace
+#else
+    GMX_UNUSED_VALUE(argc);
+    GMX_UNUSED_VALUE(argv);
 #endif
+}
 
-ProgramInfo &init(const char *realBinaryName, int *argc, char ***argv)
+void finalize()
 {
 #ifdef GMX_LIB_MPI
-    // TODO: Rewrite this to not use t_commrec once there is clarity on
-    // the approach for MPI in C++ code.
-    // TODO: Consider whether the argument broadcast would better be done
-    // in CommandLineModuleManager.
-    t_commrec cr;
-    std::memset(&cr, 0, sizeof(cr));
-    cr.nodeid = gmx_setup(argc, argv, &cr.nnodes);
-    cr.mpi_comm_mygroup = MPI_COMM_WORLD;
-    if (PAR(&cr))
+    GMX_RELEASE_ASSERT(0 < g_initializationCounter, "Excess attempt to finalize MPI");
+    // Bump the counter to record this finalization event
+    g_initializationCounter--;
+
+    if (0 == g_initializationCounter)
     {
-        broadcastArguments(&cr, argc, argv);
+        /* We sync the processes here to try to avoid problems
+         * with buggy MPI implementations that could cause
+         * unfinished processes to terminate.
+         */
+        MPI_Barrier(MPI_COMM_WORLD);
+
+        /* Apparently certain mpich implementations cause problems
+         * with MPI_Finalize. In that case comment out MPI_Finalize.
+         */
+        MPI_Finalize();
     }
 #endif
-    return ProgramInfo::init(realBinaryName, *argc, *argv);
-}
-
-ProgramInfo &init(int *argc, char ***argv)
-{
-    return init(NULL, argc, argv);
-}
-
-void finalize()
-{
-    gmx_finalize_par();
 }
 
 } // namespace gmx