--- /dev/null
- #if defined GMX_LIB_MPI && defined GMX_TARGET_BGQ
- #include <spi/include/kernel/location.h>
- #endif
-
- int gmx_physicalnode_id_hash(void)
+/*
+ * 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, 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 "basenetwork.h"
+
+#include "config.h"
+
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+#include <exception>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "gromacs/utility/cstringutil.h"
+#include "gromacs/utility/fatalerror.h"
+#include "gromacs/utility/gmxmpi.h"
+#include "gromacs/utility/programcontext.h"
+
+int gmx_gethostname(char *name, size_t len)
+{
+ if (len < 8)
+ {
+ gmx_incons("gmx_gethostname called with len<8");
+ }
+#if defined(HAVE_UNISTD_H) && !defined(__native_client__)
+ if (gethostname(name, len-1) != 0)
+ {
+ std::strncpy(name, "unknown", 8);
+ return -1;
+ }
+ return 0;
+#else
+ std::strncpy(name, "unknown", 8);
+ return -1;
+#endif
+}
+
+gmx_bool gmx_mpi_initialized(void)
+{
+#ifndef GMX_MPI
+ return 0;
+#else
+ int n;
+ MPI_Initialized(&n);
+
+ return n;
+#endif
+}
+
+int gmx_node_num(void)
+{
+#ifndef GMX_MPI
+ return 1;
+#else
+ int i;
+ (void) MPI_Comm_size(MPI_COMM_WORLD, &i);
+ return i;
+#endif
+}
+
+int gmx_node_rank(void)
+{
+#ifndef GMX_MPI
+ return 0;
+#else
+ int i;
+ (void) MPI_Comm_rank(MPI_COMM_WORLD, &i);
+ return i;
+#endif
+}
+
- int gmx_hostname_num()
- {
- #ifndef GMX_MPI
- return 0;
- #else
- #ifdef GMX_THREAD_MPI
- /* thread-MPI currently puts the thread number in the process name,
- * we might want to change this, as this is inconsistent with what
- * most MPI implementations would do when running on a single node.
- */
- return 0;
- #else
- int resultlen, hostnum, i, j;
- char mpi_hostname[MPI_MAX_PROCESSOR_NAME], hostnum_str[MPI_MAX_PROCESSOR_NAME];
++static int mpi_hostname_hash(void)
+{
+ int hash_int;
+
+#ifndef GMX_LIB_MPI
+ /* We have a single physical node */
+ hash_int = 0;
+#else
+ int resultlen;
+ char mpi_hostname[MPI_MAX_PROCESSOR_NAME];
+
+ /* This procedure can only differentiate nodes with different names.
+ * Architectures where different physical nodes have identical names,
+ * such as IBM Blue Gene, should use an architecture specific solution.
+ */
+ MPI_Get_processor_name(mpi_hostname, &resultlen);
+
+ /* The string hash function returns an unsigned int. We cast to an int.
+ * Negative numbers are converted to positive by setting the sign bit to 0.
+ * This makes the hash one bit smaller.
+ * A 63-bit hash (with 64-bit int) should be enough for unique node hashes,
+ * even on a million node machine. 31 bits might not be enough though!
+ */
+ hash_int =
+ (int)gmx_string_fullhash_func(mpi_hostname, gmx_string_hash_init);
+ if (hash_int < 0)
+ {
+ hash_int -= INT_MIN;
+ }
+#endif
+
+ return hash_int;
+}
+
- MPI_Get_processor_name(mpi_hostname, &resultlen);
- #ifdef GMX_TARGET_BGQ
++#if defined GMX_LIB_MPI && defined GMX_TARGET_BGQ
++#include <spi/include/kernel/location.h>
+
- #else
- /* This procedure can only differentiate nodes with host names
- * that end on unique numbers.
- */
- i = 0;
- j = 0;
- /* Only parse the host name up to the first dot */
- while (i < resultlen && mpi_hostname[i] != '.')
- {
- if (std::isdigit(mpi_hostname[i]))
- {
- hostnum_str[j++] = mpi_hostname[i];
- }
- i++;
- }
- hostnum_str[j] = '\0';
- if (j == 0)
- {
- hostnum = 0;
- }
- else
- {
- /* Use only the last 9 decimals, so we don't overflow an int */
- hostnum = std::strtol(hostnum_str + std::max(0, j-9), NULL, 10);
- }
- #endif
++static int bgq_nodenum(void)
++{
++ int hostnum;
+ Personality_t personality;
+ Kernel_GetPersonality(&personality, sizeof(personality));
+ /* Each MPI rank has a unique coordinate in a 6-dimensional space
+ (A,B,C,D,E,T), with dimensions A-E corresponding to different
+ physical nodes, and T within each node. Each node has sixteen
+ physical cores, each of which can have up to four hardware
+ threads, so 0 <= T <= 63 (but the maximum value of T depends on
+ the confituration of ranks and OpenMP threads per
+ node). However, T is irrelevant for computing a suitable return
+ value for gmx_hostname_num().
+ */
+ hostnum = personality.Network_Config.Acoord;
+ hostnum *= personality.Network_Config.Bnodes;
+ hostnum += personality.Network_Config.Bcoord;
+ hostnum *= personality.Network_Config.Cnodes;
+ hostnum += personality.Network_Config.Ccoord;
+ hostnum *= personality.Network_Config.Dnodes;
+ hostnum += personality.Network_Config.Dcoord;
+ hostnum *= personality.Network_Config.Enodes;
+ hostnum += personality.Network_Config.Ecoord;
- std::fprintf(debug, "In gmx_hostname_num: hostname '%s', hostnum %d\n",
- mpi_hostname, hostnum);
- #ifdef GMX_TARGET_BGQ
+
+ if (debug)
+ {
- #endif
+ std::fprintf(debug,
+ "Torus ID A: %d / %d B: %d / %d C: %d / %d D: %d / %d E: %d / %d\n"
+ "Node ID T: %d / %d core: %d / %d hardware thread: %d / %d\n",
+ personality.Network_Config.Acoord,
+ personality.Network_Config.Anodes,
+ personality.Network_Config.Bcoord,
+ personality.Network_Config.Bnodes,
+ personality.Network_Config.Ccoord,
+ personality.Network_Config.Cnodes,
+ personality.Network_Config.Dcoord,
+ personality.Network_Config.Dnodes,
+ personality.Network_Config.Ecoord,
+ personality.Network_Config.Enodes,
+ Kernel_ProcessorCoreID(),
+ 16,
+ Kernel_ProcessorID(),
+ 64,
+ Kernel_ProcessorThreadID(),
+ 4);
+ }
+ return hostnum;
++}
++#endif
++
++int gmx_physicalnode_id_hash(void)
++{
++ int hash;
++
++#ifndef GMX_MPI
++ hash = 0;
++#else
++#ifdef GMX_THREAD_MPI
++ /* thread-MPI currently puts the thread number in the process name,
++ * we might want to change this, as this is inconsistent with what
++ * most MPI implementations would do when running on a single node.
++ */
++ hash = 0;
++#else
++#ifdef GMX_TARGET_BGQ
++ hash = bgq_nodenum();
++#else
++ hash = mpi_hostname_hash();
+#endif
+#endif
++#endif
++
++ if (debug)
++ {
++ fprintf(debug, "In gmx_physicalnode_id_hash: hash %d\n", hash);
++ }
++
++ return hash;
+}
+
+#ifdef GMX_LIB_MPI
+void gmx_abort(int errorno)
+{
+ const char *programName = "GROMACS";
+ try
+ {
+ programName = gmx::getProgramContext().displayName();
+ }
+ catch (const std::exception &)
+ {
+ }
+ const int nnodes = gmx_node_num();
+ const int noderank = gmx_node_rank();
+ if (nnodes > 1)
+ {
+ std::fprintf(stderr, "Halting parallel program %s on node %d out of %d\n",
+ programName, noderank, nnodes);
+ }
+ else
+ {
+ std::fprintf(stderr, "Halting program %s\n", programName);
+ }
+
+ MPI_Abort(MPI_COMM_WORLD, errorno);
+ std::exit(errorno);
+}
+#endif
--- /dev/null
- #define GMX_DOUBLE_EPS 1.11022302E-16
+/*
+ * 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, 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.
+ */
+/*! \file
+ * \brief
+ * Declares `real` and related constants.
+ *
+ * \inpublicapi
+ * \ingroup module_utility
+ */
+#ifndef GMX_UTILITY_REAL_H
+#define GMX_UTILITY_REAL_H
+
+/*! \brief Double precision accuracy */
- #define GMX_DOUBLE_MAX 1.79769312E+308
++#define GMX_DOUBLE_EPS 2.2204460492503131e-16
+
+/*! \brief Maximum double precision value - reduced 1 unit in last digit for MSVC */
- #define GMX_DOUBLE_MIN 2.22507386E-308
++#define GMX_DOUBLE_MAX 1.7976931348623157e+308
+
+/*! \brief Minimum double precision value */
- #define GMX_FLOAT_EPS 5.96046448E-08
++#define GMX_DOUBLE_MIN 2.2250738585072014e-308
+
+/*! \brief Single precision accuracy */
- #define GMX_FLOAT_MAX 3.40282346E+38
++#define GMX_FLOAT_EPS 1.19209290e-07F
+
+/*! \brief Maximum single precision value - reduced 1 unit in last digit for MSVC */
- #define GMX_FLOAT_MIN 1.17549435E-38
++#define GMX_FLOAT_MAX 3.40282346E+38F
+
+/*! \brief Minimum single precision value */
++#define GMX_FLOAT_MIN 1.175494351E-38F
+
+
+/*! \typedef real
+ * \brief Precision-dependent \Gromacs floating-point type.
+ */
+/*! \def HAVE_REAL
+ * \brief Used to check whether `real` is already defined.
+ */
+/*! \def GMX_MPI_REAL
+ * \brief MPI data type for `real`.
+ */
+/*! \def GMX_REAL_EPS
+ * \brief Accuracy for `real`.
+ */
+/*! \def GMX_REAL_MIN
+ * \brief Smallest non-zero value for `real`.
+ */
+/*! \def GMX_REAL_MAX
+ * \brief Largest finite value for `real`.
+ */
+/*! \def gmx_real_fullprecision_pfmt
+ * \brief Format string for full `real` precision.
+ */
+#ifdef GMX_DOUBLE
+
+#ifndef HAVE_REAL
+typedef double real;
+#define HAVE_REAL
+#endif
+
+#define GMX_MPI_REAL MPI_DOUBLE
+#define GMX_REAL_EPS GMX_DOUBLE_EPS
+#define GMX_REAL_MIN GMX_DOUBLE_MIN
+#define GMX_REAL_MAX GMX_DOUBLE_MAX
+#define gmx_real_fullprecision_pfmt "%21.14e"
+
+#else /* GMX_DOUBLE */
+
+#ifndef HAVE_REAL
+typedef float real;
+#define HAVE_REAL
+#endif
+
+#define GMX_MPI_REAL MPI_FLOAT
+#define GMX_REAL_EPS GMX_FLOAT_EPS
+#define GMX_REAL_MIN GMX_FLOAT_MIN
+#define GMX_REAL_MAX GMX_FLOAT_MAX
+#define gmx_real_fullprecision_pfmt "%14.7e"
+
+#endif /* GMX_DOUBLE */
+
+#endif