Merge release-5-0 into master
authorTeemu Murtola <teemu.murtola@gmail.com>
Wed, 20 Aug 2014 18:03:25 +0000 (21:03 +0300)
committerTeemu Murtola <teemu.murtola@gmail.com>
Wed, 20 Aug 2014 18:04:55 +0000 (21:04 +0300)
Conflicts:
  src/gromacs/legacyheaders/types/simple.h
    - applied gmx_unused change to basedefinitions.h
  src/gromacs/mdlib/sim_util.c
    - took adjacent changes from both branches

Change-Id: I42071be546015ede33b03a34ef0d95a5d5a3b09e

32 files changed:
1  2 
CMakeLists.txt
install-guide/install-guide.md
src/CMakeLists.txt
src/config.h.cmakein
src/gromacs/analysisdata/tests/analysisdata.cpp
src/gromacs/analysisdata/tests/histogram.cpp
src/gromacs/fft/fft5d.cpp
src/gromacs/fileio/tngio.cpp
src/gromacs/gmxana/gmx_tune_pme.c
src/gromacs/gmxlib/gmx_omp_nthreads.c
src/gromacs/legacyheaders/types/inputrec.h
src/gromacs/mdlib/nbnxn_kernels/simd_2xnn/nbnxn_kernel_simd_2xnn_common.h
src/gromacs/mdlib/nbnxn_kernels/simd_4xn/nbnxn_kernel_simd_4xn_common.h
src/gromacs/mdlib/sim_util.c
src/gromacs/mdlib/update.c
src/gromacs/pulling/pull.c
src/gromacs/pulling/pullutil.c
src/gromacs/selection/scanner.cpp
src/gromacs/selection/scanner.l
src/gromacs/selection/scanner_flex.h
src/gromacs/selection/scanner_internal.cpp
src/gromacs/selection/selelem.cpp
src/gromacs/selection/sm_compare.cpp
src/gromacs/selection/tests/nbsearch.cpp
src/gromacs/simd/tests/simd4_math.cpp
src/gromacs/simd/tests/simd_math.cpp
src/gromacs/timing/cyclecounter.h
src/gromacs/timing/wallcycle.c
src/gromacs/timing/wallcycle.h
src/gromacs/utility/basedefinitions.h
src/programs/mdrun/md.cpp
src/programs/mdrun/tests/moduletest.cpp

diff --combined CMakeLists.txt
index c91d789d2c05dece9bdaa800f58359efb49a9645,f991ff0cb46bc52ff64026ae2c2b1d1b20d42cdb..9df009f6f30253ee9193417f5335343245aa300a
@@@ -48,28 -48,75 +48,28 @@@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CM
  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
  
 -# PROJECT_VERSION should have the following structure:
 -# VERSION-dev[-SUFFIX] where the VERSION should have the for: vMajor.vMinor.vPatch
 -#
 -# The "-dev" suffix is important to keep because it makes possible to distinguish
 -# between a build from official release and a build from git release branch on a
 -# machine with no git.
 -#
 -# NOTE: when releasing the "-dev" suffix needs to be stripped off!
 -# REGRESSIONTEST_VERSION and REGRESSIONTEST_BRANCH should always be
 -# defined.
 -set(PROJECT_VERSION "5.0.1-dev")
 -# If this is a released tarball, "-dev" will not be present in
 -# PROJECT_VERSION, and REGRESSIONTEST_VERSION specifies the version
 -# number of the regressiontest tarball against which the code tarball
 -# can be tested. This will be the version of the last patch release.
 -set(REGRESSIONTEST_VERSION "5.0.1-dev")
 -# The MD5 checksum of the regressiontest tarball. Only used if "-dev"
 -# is not present in the PROJECT_VERSION
 -set(REGRESSIONTEST_MD5SUM "a07524afebca5013540d4f2f72df2dce")
 -# If this is not a released tarball, "-dev" will be present in
 -# PROJECT_VERSION, and REGRESSIONTEST_BRANCH specifies the name of the
 -# gerrit.gromacs.org branch whose HEAD can test this code, *if* this
 -# code contains all recent fixes from the corresponding code branch.
 -set(REGRESSIONTEST_BRANCH "refs/heads/release-5-0")
 -
 -set(CUSTOM_VERSION_STRING ""
 -    CACHE STRING "Custom version string (if empty, use hard-coded default)")
 -mark_as_advanced(CUSTOM_VERSION_STRING)
 -if (CUSTOM_VERSION_STRING)
 -    set(PROJECT_VERSION ${CUSTOM_VERSION_STRING})
 -endif()
 -set(LIBRARY_SOVERSION 0)
 -set(LIBRARY_VERSION ${LIBRARY_SOVERSION}.0.0)
 -# It is a bit irritating, but this has to be set separately for now!
 -SET(CPACK_PACKAGE_VERSION_MAJOR "5")
 -SET(CPACK_PACKAGE_VERSION_MINOR "0")
 -#SET(CPACK_PACKAGE_VERSION_PATCH "0")
 -
 -# The numerical gromacs version. It is 40600 for 4.6.0.
 -# The #define GMX_VERSION in gromacs/version.h is set to this value.
 -math(EXPR NUM_VERSION
 -    "${CPACK_PACKAGE_VERSION_MAJOR}*10000 + ${CPACK_PACKAGE_VERSION_MINOR}*100")
 -if(CPACK_PACKAGE_VERSION_PATCH)
 -    math(EXPR NUM_VERSION
 -         "${NUM_VERSION} + ${CPACK_PACKAGE_VERSION_PATCH}")
 -endif()
 -
 -# The API version tracks the numerical Gromacs version (for now).
 -# It is potentially different from the Gromacs version in the future, if
 -# the programs/libraries diverge from the presumably more stable API.
 -# The #define GMX_API_VERSION in version.h is set to this value to
 -# provide backward compatibility of software written against the Gromacs API.
 -set(API_VERSION ${NUM_VERSION})
 +# Set up common version variables, as well as general information about
 +# the build tree (whether the build is from a source package or from a git
 +# repository).  Also declares a few functions that will be used for generating
 +# version info files later.
 +include(gmxVersionInfo)
  
  if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND UNIX)
      set(CMAKE_INSTALL_PREFIX "/usr/local/gromacs" CACHE STRING "Installation prefix (installation will need write permissions here)" FORCE)
  endif()
  
  include(gmxBuildTypeReference)
 +include(gmxBuildTypeProfile)
  include(gmxBuildTypeTSAN)
  include(gmxBuildTypeASAN)
  include(gmxBuildTypeReleaseWithAssert)
  
  if(NOT CMAKE_BUILD_TYPE)
 -    set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel Reference RelWithAssert." FORCE)
 +    set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel Reference RelWithAssert Profile." FORCE)
      # There's no need to offer a user the choice of ThreadSanitizer
      # Set the possible values of build type for cmake-gui
      set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
 -        "MinSizeRel" "RelWithDebInfo" "Reference" "RelWithAssert")
 +        "MinSizeRel" "RelWithDebInfo" "Reference" "RelWithAssert" "Profile")
  endif()
  if(CMAKE_CONFIGURATION_TYPES)
      # Add appropriate GROMACS-specific build types for the Visual
          "List of configuration types"
          FORCE)
  endif()
 -set(build_types_with_explicit_flags RELEASE DEBUG RELWITHDEBUGINFO RELWITHASSERT MINSIZEREL)
 -
 -enable_language(C)
 -enable_language(CXX)
 +set(build_types_with_explicit_flags RELEASE DEBUG RELWITHDEBUGINFO RELWITHASSERT MINSIZEREL PROFILE)
  
  set(CPACK_PACKAGE_NAME "gromacs")
 -set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
 +set(CPACK_PACKAGE_VERSION_MAJOR ${GMX_VERSION_MAJOR})
 +set(CPACK_PACKAGE_VERSION_MINOR ${GMX_VERSION_MINOR})
 +set(CPACK_PACKAGE_VERSION_PATCH ${GMX_VERSION_PATCH})
 +set(CPACK_PACKAGE_VERSION       ${GMX_VERSION_STRING})
  set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
  set(CPACK_PACKAGE_VENDOR "gromacs.org")
  set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Gromacs - a toolkit for high-performance molecular simulation")
@@@ -117,9 -164,14 +117,9 @@@ set(MEMORYCHECK_SUPPRESSIONS_FIL
      "File that contains suppressions for the memory checker")
  include(CTest)
  
 -set(SOURCE_IS_GIT_REPOSITORY OFF)
 -set(SOURCE_IS_SOURCE_DISTRIBUTION OFF)
 -if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
 -    set(SOURCE_IS_GIT_REPOSITORY ON)
 -endif()
 -if(NOT EXISTS "${CMAKE_SOURCE_DIR}/admin/.isreposource")
 -    set(SOURCE_IS_SOURCE_DISTRIBUTION ON)
 -endif()
 +# Variables that accumulate stuff influencing the installed headers
 +set(INSTALLED_HEADER_INCLUDE_DIRS "")
 +set(INSTALLED_HEADER_DEFINITIONS "")
  
  ########################################################################
  # Check and warn if cache generated on a different host is being reused
@@@ -239,6 -291,9 +239,6 @@@ option(GMX_OPENMP "Enable OpenMP-based 
  
  option(GMX_USE_TNG "Use the TNG library for trajectory I/O" ON)
  
 -option(GMX_GIT_VERSION_INFO "Generate git version information" ${SOURCE_IS_GIT_REPOSITORY})
 -mark_as_advanced(GMX_GIT_VERSION_INFO)
 -
  if(UNIX)
      option(GMX_SYMLINK_OLD_BINARY_NAMES "Create symbolic links for pre-5.0 binary names" ON)
  endif()
@@@ -255,6 -310,10 +255,10 @@@ option(GMX_BUILD_FOR_COVERAG
         OFF)
  mark_as_advanced(GMX_BUILD_FOR_COVERAGE)
  
+ option(GMX_DEVELOPER_BUILD
+     "Enable Developer convenience features: always build unit-tests"
+     OFF)
+ mark_as_advanced(GMX_DEVELOPER_BUILD)
  
  ######################################################################
  # Detect OpenMP support
@@@ -272,7 -331,7 +276,7 @@@ include(gmxManageOpenMP
  # The cmake/Check{C,CXX}CompilerFlag.cmake files in the GROMACS distribution
  # are used with permission from CMake v3.0.0 so that GROMACS can detect
  # invalid options with the Intel Compilers, and we have added a line
- # to detect warnings with the Fujitsu compilers on K computer.
+ # to detect warnings with the Fujitsu compilers on K computer and ICC.
  # CMake-3.0 also has a bug where the FAIL_REGEX pattern for AIX contains
  # a semicolon. Since this is also used as a separator in lists inside CMake,
  # that string ends up being split into two separate patterns, and the last
@@@ -308,12 -367,14 +312,12 @@@ if(GMX_SIMD STREQUAL "AVX_256
  endif()
  
  
 -
 -set(PKG_CFLAGS "")
  if(GMX_DOUBLE)
      add_definitions(-DGMX_DOUBLE)
 -    set(PKG_CFLAGS "${PKG_CFLAGS} -DGMX_DOUBLE")
 +    list(APPEND INSTALLED_HEADER_DEFINITIONS "-DGMX_DOUBLE")
  endif()
  if(GMX_SOFTWARE_INVSQRT)
 -  set(PKG_CFLAGS "${PKG_CFLAGS} -DGMX_SOFTWARE_INVSQRT")
 +    list(APPEND INSTALLED_HEADER_DEFINITIONS "-DGMX_SOFTWARE_INVSQRT")
  endif()
  
  if(WIN32 AND NOT CYGWIN)
@@@ -481,6 -542,25 +485,6 @@@ if(WIN32 AND NOT CYGWIN
      add_definitions(-DNOMINMAX)
  endif()
  
 -# only bother with finding git and using version.h if the source is a git repo
 -if(GMX_GIT_VERSION_INFO)
 -    if (NOT SOURCE_IS_GIT_REPOSITORY)
 -        message(FATAL_ERROR
 -            "Cannot generate git version information from source tree not under git. "
 -            "Set GMX_GIT_VERSION_INFO=OFF to proceed.")
 -    endif()
 -    # We need at least git v1.5.3 be able to parse git's date output. If not
 -    # found or the version is too small, we can't generate version information.
 -    find_package(Git)
 -
 -    if(NOT GIT_FOUND OR GIT_VERSION_STRING VERSION_LESS "1.5.3")
 -        message(FATAL_ERROR
 -            "No compatible git version found (>= 1.5.3 required). "
 -            "Won't be able to generate development version information. "
 -            "Set GMX_GIT_VERSION_INFO=OFF to proceed.")
 -    endif()
 -endif()
 -
  # Detect boost unless GMX_EXTERNAL_BOOST is explicitly OFF
  # Used for default if GMX_EXTERNAL_BOOST is not defined (first CMake pass)
  if(NOT DEFINED GMX_EXTERNAL_BOOST OR GMX_EXTERNAL_BOOST)
@@@ -516,6 -596,12 +520,6 @@@ if (GMX_BUILD_UNITTESTS AND NOT HAVE_LI
          "Either set GMX_BUILD_UNITTESTS=OFF or tell CMake how to find a working version of libxml2.")
  endif()
  
 -########################################################################
 -# Generate development version info for cache
 -########################################################################
 -# set(GEN_VERSION_INFO_INTERNAL "ON")
 -# include(gmxGenerateVersionString)
 -
  ########################################################################
  # Our own GROMACS tests
  ########################################################################
@@@ -525,6 -611,10 +529,6 @@@ include_directories(BEFORE ${CMAKE_SOUR
  include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/thread_mpi/include)
  # Required for config.h, maybe should only be set in src/CMakeLists.txt
  include_directories(BEFORE ${CMAKE_BINARY_DIR}/src)
 -# Required for gmx_header_config_gen.h to be found before installation
 -include_directories(BEFORE ${CMAKE_BINARY_DIR}/src/gromacs/utility)
 -# Required for now to make old code compile
 -include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/gromacs/legacyheaders)
  
  include(gmxTestInlineASM)
  gmx_test_inline_asm_gcc_x86(GMX_X86_GCC_INLINE_ASM)
@@@ -639,10 -729,7 +643,7 @@@ if(GMX_LOAD_PLUGINS
    # so, should we use plug-ins?
    if((WIN32 AND NOT CYGWIN) OR (HAVE_DLOPEN AND BUILD_SHARED_LIBS))
      if(NOT VMD_QUIETLY)
-       MESSAGE(STATUS
-           "Found the ability to use plug-ins when building shared libaries, "
-           "so will compile to use plug-ins (e.g. to read VMD-supported file "
-           "formats).")
+       MESSAGE(STATUS "Using dynamic plugins (e.g VMD-supported file formats)")
      endif()
      if(NOT GMX_VMD_PLUGIN_PATH)
        find_package(VMD)
@@@ -721,6 -808,7 +722,6 @@@ else(
      set(GMX_EXE_LINKER_FLAGS ${GMX_EXE_LINKER_FLAGS} ${OpenMP_LINKER_FLAGS})
      set(GMX_SHARED_LINKER_FLAGS ${GMX_SHARED_LINKER_FLAGS} ${OpenMP_SHARED_LINKER_FLAGS})
  endif()
 -set(PKG_CFLAGS "${PKG_CFLAGS} ${OpenMP_C_FLAGS}")
  
  ########################################################################
  # Specify install locations
@@@ -737,24 -825,17 +738,24 @@@ mark_as_advanced(GMX_LIB_INSTALL_DIR GM
  
  # These variables are used internally to provide a central location for
  # customizing the install locations.
 -set(LIB_INSTALL_DIR  ${GMX_LIB_INSTALL_DIR})
 -set(BIN_INSTALL_DIR  bin)
 -set(DATA_INSTALL_DIR share/${GMX_DATA_INSTALL_DIR})
 -set(MAN_INSTALL_DIR  share/man)
 -set(INCL_INSTALL_DIR include)
 +set(LIB_INSTALL_DIR       ${GMX_LIB_INSTALL_DIR})
 +set(BIN_INSTALL_DIR       bin)
 +set(DATA_INSTALL_DIR      share/${GMX_DATA_INSTALL_DIR})
 +set(MAN_INSTALL_DIR       share/man)
 +# If the nesting level wrt. the installation root is changed,
 +# gromacs-config.cmake.cmakein needs to be adapted.
 +set(CMAKE_INSTALL_DIR     share/cmake)
 +# TODO: Make GMXRC adapt if this is changed
 +set(PKGCONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/pkgconfig)
 +set(INCL_INSTALL_DIR      include)
  
  # These variables get written into config.h for use in finding the data
  # directories.
  set(GMXLIB_SEARCH_DIR share/${GMX_DATA_INSTALL_DIR}/top)
  set(GMXLIB_FALLBACK   ${CMAKE_INSTALL_PREFIX}/${DATA_INSTALL_DIR}/top)
  
 +list(APPEND INSTALLED_HEADER_INCLUDE_DIRS ${INCL_INSTALL_DIR})
 +
  # Binary and library suffix options
  include(gmxManageSuffixes)
  
@@@ -800,14 -881,15 +801,14 @@@ install(FILES COPYING DESTINATION ${DAT
  
  if(GMX_EXTERNAL_BOOST)
      include_directories(${Boost_INCLUDE_DIRS})
 -    set(PKG_CFLAGS "${PKG_CFLAGS} -I${Boost_INCLUDE_DIRS}")
 +    list(APPEND INSTALLED_HEADER_INCLUDE_DIRS ${Boost_INCLUDE_DIRS})
  else()
      include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/boost)
 +    list(APPEND INSTALLED_HEADER_INCLUDE_DIRS ${INCL_INSTALL_DIR}/gromacs/external/boost)
 +    list(APPEND INSTALLED_HEADED_DEFINITIONS "-DBOOST_NO_TYPEID")
      # typeid not supported for minimal internal version
      # (would add significant amount of code)
      add_definitions(-DBOOST_NO_TYPEID)
 -    # TODO: Propagate the above settings to the installed CMakeFiles.txt template
 -    # (from share/template/)
 -    set(PKG_CFLAGS "${PKG_CFLAGS} -DBOOST_NO_TYPEID -I${CMAKE_INSTALL_PREFIX}/${INCL_INSTALL_DIR}/gromacs/external/boost")
      if (NOT GMX_BUILD_MDRUN_ONLY)
          install(DIRECTORY ${CMAKE_SOURCE_DIR}/src/external/boost/boost
                  DESTINATION ${INCL_INSTALL_DIR}/gromacs/external/boost
index b914782c4bb4dada8c75be1dbe0af8f3ed2c6666,67eb2c7d06146e9e1a2440901115f42c02f1838d..5964f05f335d34a99eced0bd73cf52e6f5c20bee
@@@ -13,7 -13,7 +13,7 @@@ at <http://www.gromacs.org/Documentatio
  3. Get and unpack the latest version of the GROMACS tarball.
  4. Make a separate build directory and change to it. 
  5. Run `cmake` with the path to the source as an argument
- 6. Run `make`, `make test`, and `make install`
+ 6. Run `make`, `make check`, and `make install`
  
  Or, as a sequence of commands to execute:
  
@@@ -23,7 -23,7 +23,7 @@@
      cd build
      cmake .. -DGMX_BUILD_OWN_FFTW=ON -DREGRESSIONTEST_DOWNLOAD=ON
      make
-     make test
+     make check
      sudo make install
      source /usr/local/gromacs/bin/GMXRC
  
@@@ -650,13 -650,6 +650,13 @@@ CMakeLists.txt
      is determined by CMake.
      The name of the directory can be changed using `GMX_LIB_INSTALL_DIR` CMake
      variable.
 +`lib/pkgconfig/`
 +  : Information about the installed `libgromacs` library for `pkg-config` is
 +    installed here.  The `lib/` part adapts to the installation location of the
 +    libraries.  The installed files contain the installation prefix as absolute
 +    paths.
 +`share/cmake/`
 +  : CMake package configuration files are installed here.
  `share/gromacs/`
    : Various data files and some documentation go here.
      The `gromacs` part can be changed using `GMX_DATA_INSTALL_DIR`. Using this
diff --combined src/CMakeLists.txt
index fb69a91cfe3838db27dc1d3aac20c8981593f88a,4764df0ac3e8536be4f593d108015120a4bba15a..a263d4f7217b62f8da1f461062a1cd6d8bd1f9f4
@@@ -43,10 -43,12 +43,13 @@@ if(GMX_GPU
  endif()
  
  configure_file(config.h.cmakein config.h)
 +configure_file(gmxpre-config.h.cmakein gmxpre-config.h)
  configure_file(buildinfo.h.cmakein buildinfo.h ESCAPE_QUOTES)
  
  if (BUILD_TESTING)
+     if(NOT GMX_DEVELOPER_BUILD)
+         set(UNITTEST_TARGET_OPTIONS EXCLUDE_FROM_ALL)
+     endif()
      if (GMX_BUILD_UNITTESTS)
          add_subdirectory(external/gmock-1.7.0)
      endif()
diff --combined src/config.h.cmakein
index 3b48fc0342934f9ea7a43fbdc8d5a45e925e7aaf,4aa43dc6121e4166fc097fa00ef82fec439c3acf..f7304583407f95e5a19a0867f2b09566749072fa
  /* Binary directory for the build */
  #cmakedefine CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@"
  
 -/* Turn off water-water neighborlist optimization only - not used right now */
 -#cmakedefine DISABLE_WATERWATER_NLIST
 -
 -/* Turn off all water neighborlist optimization - not used right now */
 -#cmakedefine DISABLE_WATER_NLIST
 -
  /* IEEE754 floating-point format. Memory layout is defined by macros
   * GMX_IEEE754_BIG_ENDIAN_BYTE_ORDER and GMX_IEEE754_BIG_ENDIAN_WORD_ORDER. 
   */
  /* Target platform is BlueGene/Q */
  #cmakedefine GMX_TARGET_BGQ
  
 +/** Define if we are building for Cygwin */
 +#cmakedefine GMX_CYGWIN
 +
 +/** Define if we have sufficient C++11 support */
 +#cmakedefine GMX_CXX11
 +
  /* GCC bug in AVX maskload/maskstore arguments - worked around internally */
  #cmakedefine GMX_SIMD_X86_AVX_GCC_MASKLOAD_BUG
  
  /* String for SIMD instruction choice (for writing to log files and stdout) */
  #define GMX_SIMD_STRING "@GMX_SIMD@"
  
+ /* Calling convention string (if any) for routines with SIMD variable args */
+ #define gmx_simdcall @GMX_SIMD_CALLING_CONVENTION@
  /* Integer byte order is big endian. */
  #cmakedefine GMX_INTEGER_BIG_ENDIAN
  
  /* Define if SIGUSR1 is present */
  #cmakedefine HAVE_SIGUSR1
  
 -/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
 -#cmakedefine _LARGEFILE_SOURCE
 -
 -/* Define for large files, on AIX-style hosts. */
 -#cmakedefine _LARGE_FILES
 -
 -/* Some systems requires this to be set to 64 for large file support */
 -#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@
 -
 -/* Build special-purpose mdrun library */
 -#cmakedefine GMX_FAHCORE   
 -
  /* Enable gromacs quotes */
  #cmakedefine GMX_COOL_QUOTES
  
 -#ifdef GMX_FAHCORE
 -#define FULLINDIRECT 1
 -#define USE_FAH_XDR  1
 -#include "swindirect.h"
 -#endif
 -
  /* default name mangling maybe wrong on exotic plattforms */
  #define F77_FUNC(name,NAME) name ## _
  
index 1d99f44b1a1b03a1b74b61384435c3d3b59df264,9149a5177c616217ae0b55feff00651d27a53ca7..d8949f6c8a0c73b6e70935289628feaad6e44e63
@@@ -45,8 -45,6 +45,8 @@@
   * \author Teemu Murtola <teemu.murtola@gmail.com>
   * \ingroup module_analysisdata
   */
 +#include "gmxpre.h"
 +
  #include <gmock/gmock.h>
  #include <gtest/gtest.h>
  
@@@ -141,6 -139,7 +141,7 @@@ TEST(AnalysisDataInitializationTest, Ch
      EXPECT_NO_THROW_GMX(data.addModule(mod2));
  }
  
+ #if GTEST_HAS_TYPED_TEST
  
  /********************************************************************
   * Input data for tests below.
@@@ -448,4 -447,19 +449,19 @@@ TYPED_TEST(AnalysisDataCommonTest, Limi
      ASSERT_NO_THROW_GMX(AnalysisDataTest::presentAllData());
  }
  
+ #else
+ /* A dummy test that at least signals that something is missing if one runs the
+  * unit test executable itself.
+  */
+ TEST(DISABLED_AnalysisDataCommonTest, GenericTests)
+ {
+     ADD_FAILURE()
+     << "Tests for generic AnalysisData functionality require support for "
+     << "Google Test typed tests, which was not available when the tests "
+     << "were compiled.";
+ }
+ #endif
  } // namespace
index 7998927e48abdf4d18ee3f8ea785828de3129db5,18ec9ce1b9315c2ab9a1cf8aafa6219febd5a33f..baf6774786dff981295a91a577a78a58e67b50b1
@@@ -46,8 -46,6 +46,8 @@@
   * \author Teemu Murtola <teemu.murtola@gmail.com>
   * \ingroup module_analysisdata
   */
 +#include "gmxpre.h"
 +
  #include <gtest/gtest.h>
  
  #include "gromacs/analysisdata/analysisdata.h"
@@@ -490,7 -488,6 +490,6 @@@ class AverageInputDat
  class MockAverageHistogram : public gmx::AbstractAverageHistogram
  {
      public:
-         MockAverageHistogram() {}
          //! Creates a histogram module with defined bin parameters.
          explicit MockAverageHistogram(const gmx::AnalysisHistogramSettings &settings)
              : AbstractAverageHistogram(settings)
index 27d42915fb9065932562a5e7ba93b54a1a272d63,94fde316da46617bedc65f40f2117a72855e52dd..69a689aaa8fe469f03c8814fe902fb63c5e6928a
@@@ -32,9 -32,9 +32,9 @@@
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
 +
 +#include "config.h"
  
  #include <algorithm>
  
@@@ -76,7 -76,7 +76,7 @@@
  FILE* debug = 0;
  #endif
  
 -#include "gmx_fatal.h"
 +#include "gromacs/utility/fatalerror.h"
  
  
  #ifdef GMX_FFT_FFTW3
@@@ -89,19 -89,18 +89,18 @@@ static tMPI::mutex big_fftw_mutex
  #define FFTW_UNLOCK try { big_fftw_mutex.unlock(); } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR
  #endif /* GMX_FFT_FFTW3 */
  
+ #ifdef GMX_MPI
  /* largest factor smaller than sqrt */
  static int lfactor(int z)
  {
-     int i;
-     for (i = static_cast<int>(sqrt(static_cast<double>(z)));; i--)
+     int i = static_cast<int>(sqrt(static_cast<double>(z)));
+     while (z%i != 0)
      {
-         if (z%i == 0)
-         {
-             return i;
-         }
+         i--;
      }
-     return 1;
+     return i;
  }
+ #endif
  
  /* largest factor */
  static int l2factor(int z)
      int i;
      if (z == 1)
      {
-         return 1;
+         i = 1;
      }
-     for (i = z/2;; i--)
+     else
      {
-         if (z%i == 0)
+         i = z/2;
+         while (z%i != 0)
          {
-             return i;
+             i--;
          }
      }
-     return 1;
+     return i;
  }
  
  /* largest prime factor: WARNING: slow recursion, only use for small numbers */
index e0a7f42e41b912e9dd9393193cc70b5d7f503bdd,1fea9473e73b1ed3947bd897315ca7d045f98af4..31447ee6d395433836a97be0379f80998d581975
   * 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 "tngio.h"
  
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "config.h"
  
  #ifdef HAVE_UNISTD_H
  #include <unistd.h>
  #endif
  
  #include "gromacs/legacyheaders/copyrite.h"
 -#include "gromacs/legacyheaders/gmx_fatal.h"
 -#include "gromacs/legacyheaders/main.h"
 -#include "gromacs/legacyheaders/physics.h"
 +#include "gromacs/legacyheaders/types/ifunc.h"
 +
 +#include "gromacs/fileio/gmxfio.h"
 +#include "gromacs/math/units.h"
  #include "gromacs/math/utilities.h"
 +#include "gromacs/topology/topology.h"
 +#include "gromacs/utility/basenetwork.h"
  #include "gromacs/utility/common.h"
 +#include "gromacs/utility/fatalerror.h"
  #include "gromacs/utility/gmxassert.h"
  #include "gromacs/utility/programcontext.h"
 -#include "gmxfio.h"
  
  static const char *modeToVerb(char mode)
  {
+     const char *p;
      switch (mode)
      {
          case 'r':
-             return "reading";
+             p = "reading";
              break;
          case 'w':
-             return "writing";
+             p = "writing";
              break;
          case 'a':
-             return "appending";
+             p = "appending";
              break;
          default:
              gmx_fatal(FARGS, "Invalid file opening mode %c", mode);
-             return "";
+             p = "";
+             break;
      }
+     return p;
  }
  
  void gmx_tng_open(const char       *filename,
index 7956218555852d45d8cc69de4228730919c375d3,112e87273262698a714f1c5bdcbe1413eefca659..d5222db2704d90329f4aa43c13099d8316335d08
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
 +
 +#include "config.h"
  
 +#include <stdlib.h>
  #include <time.h>
  #ifdef HAVE_SYS_TIME_H
  #include <sys/time.h>
  #endif
  
 -#include "gromacs/commandline/pargs.h"
 -#include "typedefs.h"
 -#include "types/commrec.h"
 -#include "gromacs/utility/smalloc.h"
 -#include "vec.h"
 -#include "copyrite.h"
 +#include "gromacs/legacyheaders/typedefs.h"
 +#include "gromacs/legacyheaders/types/commrec.h"
 +#include "gromacs/math/vec.h"
  #include "gromacs/fileio/tpxio.h"
  #include "gromacs/utility/cstringutil.h"
 -#include "readinp.h"
 -#include "calcgrid.h"
 -#include "checkpoint.h"
 -#include "macros.h"
 +#include "gromacs/legacyheaders/readinp.h"
 +#include "gromacs/legacyheaders/calcgrid.h"
 +#include "gromacs/legacyheaders/checkpoint.h"
 +#include "gromacs/legacyheaders/macros.h"
  #include "gmx_ana.h"
 -#include "names.h"
 -#include "perf_est.h"
 -#include "inputrec.h"
 +#include "gromacs/legacyheaders/names.h"
 +#include "gromacs/legacyheaders/perf_est.h"
 +#include "gromacs/legacyheaders/inputrec.h"
  #include "gromacs/timing/walltime_accounting.h"
  #include "gromacs/math/utilities.h"
  
 -#include "gmx_fatal.h"
 +#include "gromacs/commandline/pargs.h"
 +#include "gromacs/utility/baseversion.h"
 +#include "gromacs/utility/fatalerror.h"
 +#include "gromacs/utility/smalloc.h"
  
  /* Enum for situations that can occur during log file parsing, the
   * corresponding string entries can be found in do_the_tests() in
@@@ -144,6 -143,29 +144,6 @@@ static void cleandata(t_perf *perfdata
  }
  
  
 -static gmx_bool is_equal(real a, real b)
 -{
 -    real diff, eps = 1.0e-7;
 -
 -
 -    diff = a - b;
 -
 -    if (diff < 0.0)
 -    {
 -        diff = -diff;
 -    }
 -
 -    if (diff < eps)
 -    {
 -        return TRUE;
 -    }
 -    else
 -    {
 -        return FALSE;
 -    }
 -}
 -
 -
  static void remove_if_exists(const char *fn)
  {
      if (gmx_fexist(fn))
@@@ -531,8 -553,8 +531,8 @@@ static gmx_bool analyze_data
      fprintf(fp, "\n");
  
      /* Only mention settings if they were modified: */
 -    bRefinedCoul = !is_equal(info->rcoulomb[k_win], info->rcoulomb[0]);
 -    bRefinedVdW  = !is_equal(info->rvdw[k_win], info->rvdw[0]    );
 +    bRefinedCoul = !gmx_within_tol(info->rcoulomb[k_win], info->rcoulomb[0], GMX_REAL_EPS);
 +    bRefinedVdW  = !gmx_within_tol(info->rvdw[k_win], info->rvdw[0], GMX_REAL_EPS);
      bRefinedGrid = !(info->nkx[k_win] == info->nkx[0] &&
                       info->nky[k_win] == info->nky[0] &&
                       info->nkz[k_win] == info->nkz[0]);
@@@ -594,25 -616,25 +594,25 @@@ static void get_program_paths(gmx_bool 
      {
          if ( (cp = getenv("MPIRUN")) != NULL)
          {
 -            *cmd_mpirun = strdup(cp);
 +            *cmd_mpirun = gmx_strdup(cp);
          }
          else
          {
 -            *cmd_mpirun = strdup(def_mpirun);
 +            *cmd_mpirun = gmx_strdup(def_mpirun);
          }
      }
      else
      {
 -        *cmd_mpirun = strdup(empty_mpirun);
 +        *cmd_mpirun = gmx_strdup(empty_mpirun);
      }
  
      if ( (cp = getenv("MDRUN" )) != NULL)
      {
 -        *cmd_mdrun  = strdup(cp);
 +        *cmd_mdrun  = gmx_strdup(cp);
      }
      else
      {
 -        *cmd_mdrun  = strdup(def_mdrun);
 +        *cmd_mdrun  = gmx_strdup(def_mdrun);
      }
  }
  
@@@ -787,6 -809,11 +787,11 @@@ static void modify_PMEsettings
      sfree(ir);
  }
  
+ static gmx_bool can_scale_rvdw(int vdwtype)
+ {
+     return (evdwCUT == vdwtype ||
+             evdwPME == vdwtype);
+ }
  
  #define EPME_SWITCHED(e) ((e) == eelPMESWITCH || (e) == eelPMEUSERSWITCH)
  
@@@ -936,7 -963,7 +941,7 @@@ static void make_benchmark_tprs
      fprintf(fp, " No.   scaling  rcoulomb");
      fprintf(fp, "  nkx  nky  nkz");
      fprintf(fp, "   spacing");
-     if (evdwCUT == ir->vdwtype)
+     if (can_scale_rvdw(ir->vdwtype))
      {
          fprintf(fp, "      rvdw");
      }
          {
              /* Determine which Coulomb radii rc to use in the benchmarks */
              add = (rmax-rmin)/(*ntprs-1);
 -            if (is_equal(rmin, info->rcoulomb[0]))
 +            if (gmx_within_tol(rmin, info->rcoulomb[0], GMX_REAL_EPS))
              {
                  ir->rcoulomb = rmin + j*add;
              }
 -            else if (is_equal(rmax, info->rcoulomb[0]))
 +            else if (gmx_within_tol(rmax, info->rcoulomb[0], GMX_REAL_EPS))
              {
                  ir->rcoulomb = rmin + (j-1)*add;
              }
                  ir->rlist = ir->rcoulomb + nlist_buffer;
              }
  
-             if (bScaleRvdw && evdwCUT == ir->vdwtype)
+             if (bScaleRvdw && can_scale_rvdw(ir->vdwtype))
              {
-                 if (ecutsVERLET == ir->cutoff_scheme)
+                 if (ecutsVERLET == ir->cutoff_scheme ||
+                     evdwPME == ir->vdwtype)
                  {
-                     /* With Verlet, the van der Waals radius must always equal the Coulomb radius */
+                     /* With either the Verlet cutoff-scheme or LJ-PME,
+                        the van der Waals radius must always equal the
+                        Coulomb radius */
                      ir->rvdw = ir->rcoulomb;
                  }
                  else
          fprintf(fp, "%4d%10f%10f", j, fac, ir->rcoulomb);
          fprintf(fp, "%5d%5d%5d", ir->nkx, ir->nky, ir->nkz);
          fprintf(fp, " %9f ", info->fsx[j]);
-         if (evdwCUT == ir->vdwtype)
+         if (can_scale_rvdw(ir->vdwtype))
          {
              fprintf(fp, "%10f", ir->rvdw);
          }
          fprintf(fp, "  %-14s\n", fn_bench_tprs[j]);
  
          /* Make it clear to the user that some additional settings were modified */
 -        if (!is_equal(ir->rvdw, info->rvdw[0])
 -            || !is_equal(ir->rlistlong, info->rlistlong[0]) )
 +        if (!gmx_within_tol(ir->rvdw, info->rvdw[0], GMX_REAL_EPS)
 +            || !gmx_within_tol(ir->rlistlong, info->rlistlong[0], GMX_REAL_EPS) )
          {
              bNote = TRUE;
          }
@@@ -1623,13 -1653,13 +1631,13 @@@ static void check_input
      /* Add test scenarios if rmin or rmax were set */
      if (*ntprs <= 2)
      {
 -        if (!is_equal(*rmin, rcoulomb) && (*ntprs == 1) )
 +        if (!gmx_within_tol(*rmin, rcoulomb, GMX_REAL_EPS) && (*ntprs == 1) )
          {
              (*ntprs)++;
              fprintf(stderr, "NOTE: Setting -rmin to %g changed -ntpr to %d\n",
                      *rmin, *ntprs);
          }
 -        if (!is_equal(*rmax, rcoulomb) && (*ntprs == 1) )
 +        if (!gmx_within_tol(*rmax, rcoulomb, GMX_REAL_EPS) && (*ntprs == 1) )
          {
              (*ntprs)++;
              fprintf(stderr, "NOTE: Setting -rmax to %g changed -ntpr to %d\n",
      }
      old = *ntprs;
      /* If one of rmin, rmax is set, we need 2 tpr files at minimum */
 -    if (!is_equal(*rmax, rcoulomb) || !is_equal(*rmin, rcoulomb) )
 +    if (!gmx_within_tol(*rmax, rcoulomb, GMX_REAL_EPS) || !gmx_within_tol(*rmin, rcoulomb, GMX_REAL_EPS) )
      {
          *ntprs = max(*ntprs, 2);
      }
  
      /* If both rmin, rmax are set, we need 3 tpr files at minimum */
 -    if (!is_equal(*rmax, rcoulomb) && !is_equal(*rmin, rcoulomb) )
 +    if (!gmx_within_tol(*rmax, rcoulomb, GMX_REAL_EPS) && !gmx_within_tol(*rmin, rcoulomb, GMX_REAL_EPS) )
      {
          *ntprs = max(*ntprs, 3);
      }
  
      if (*ntprs > 1)
      {
 -        if (is_equal(*rmin, rcoulomb) && is_equal(rcoulomb, *rmax)) /* We have just a single rc */
 +        if (gmx_within_tol(*rmin, rcoulomb, GMX_REAL_EPS) && gmx_within_tol(rcoulomb, *rmax, GMX_REAL_EPS)) /* We have just a single rc */
          {
              fprintf(stderr, "WARNING: Resetting -ntpr to 1 since no Coulomb radius scaling is requested.\n"
                      "Please set rmin < rmax to test Coulomb radii in the [rmin, rmax] interval\n"
@@@ -2356,8 -2386,7 +2364,8 @@@ int gmx_tune_pme(int argc, char *argv[]
      sep_line(fp);
      fprintf(fp, "\n      P E R F O R M A N C E   R E S U L T S\n");
      sep_line(fp);
 -    fprintf(fp, "%s for Gromacs %s\n", ShortProgram(), GromacsVersion());
 +    fprintf(fp, "%s for Gromacs %s\n", output_env_get_program_display_name(oenv),
 +            gmx_version());
      if (!bThreads)
      {
          fprintf(fp, "Number of ranks         : %d\n", nnodes);
index 14f4de935679b48ae8cc9341a95bc59d65290521,68fdbb37e7074d423a457407926c9c19e29bb644..76824dee392284ae76893bd3c5a40f5b5389553e
   * the research papers on the package. Check out http://www.gromacs.org.
   */
  
 +#include "gmxpre.h"
 +
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <assert.h>
  
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "config.h"
  
 -#include "gmx_fatal.h"
 -#include "typedefs.h"
 -#include "macros.h"
 -#include "network.h"
 -#include "copyrite.h"
 -#include "gmx_omp_nthreads.h"
 -#include "md_logging.h"
 +#include "gromacs/legacyheaders/typedefs.h"
 +#include "gromacs/legacyheaders/types/commrec.h"
 +#include "gromacs/legacyheaders/macros.h"
 +#include "gromacs/legacyheaders/network.h"
 +#include "gromacs/legacyheaders/copyrite.h"
 +#include "gromacs/legacyheaders/gmx_omp_nthreads.h"
 +#include "gromacs/legacyheaders/md_logging.h"
  
 +#include "gromacs/utility/cstringutil.h"
 +#include "gromacs/utility/fatalerror.h"
  #include "gromacs/utility/gmxomp.h"
  
  /** Structure with the number of threads for each OpenMP multi-threaded
@@@ -147,9 -145,9 +147,9 @@@ static void pick_module_nthreads(FILE *
           * OMP_NUM_THREADS also has to be set */
          if (bFullOmpSupport && getenv("OMP_NUM_THREADS") == NULL)
          {
-             gmx_fatal(FARGS, "%s=%d is set, the default number of threads also "
-                       "needs to be set with OMP_NUM_THREADS!",
-                       modth_env_var[m], nth);
+             gmx_warning("%s=%d is set, the default number of threads also "
+                         "needs to be set with OMP_NUM_THREADS!",
+                         modth_env_var[m], nth);
          }
  
          /* with the group scheme warn if any env var except PME is set */
index e2626e6d44383e32fb03d71c952eac35ebe5a831,10fa0da0d3e38b70a139ce5731528ee6adba2666..d6f7433ef83644899c641fb2b909dffa8ced89e5
  #ifndef _inputrec_h_
  #define _inputrec_h_
  
 +#include <stdio.h>
  
 -#include "simple.h"
 -#include "enums.h"
 -#include "../sysstuff.h"
 +#include "gromacs/legacyheaders/types/simple.h"
 +#include "gromacs/legacyheaders/types/enums.h"
  #include "../../swap/enums.h"
  
  #ifdef __cplusplus
@@@ -225,13 -225,15 +225,15 @@@ typedef struct 
      t_pull_coord  *coord;      /* the pull coordinates */
  
      /* Variables not present in mdp, but used at run time */
-     t_pull_group  *dyna;       /* dynamic groups for use with local constraints */
-     rvec          *rbuf;       /* COM calculation buffer */
-     dvec          *dbuf;       /* COM calculation buffer */
-     double        *dbuf_cyl;   /* cylinder ref. groups COM calculation buffer */
+     t_pull_group  *dyna;         /* dynamic groups for use with local constraints */
+     gmx_bool       bSetPBCatoms; /* Do we need to set x_pbc for the groups? */
  
-     FILE          *out_x;      /* output file for pull data */
-     FILE          *out_f;      /* output file for pull data */
+     rvec          *rbuf;         /* COM calculation buffer */
+     dvec          *dbuf;         /* COM calculation buffer */
+     double        *dbuf_cyl;     /* cylinder ref. groups COM calculation buffer */
+     FILE          *out_x;        /* output file for pull data */
+     FILE          *out_f;        /* output file for pull data */
  } t_pull;
  
  
index 89310bd7dceafd9733995bad573ebdda8f2e64fd,698c5d389c6827a21184395ba5e1cd3fcd86a92d..228fa8b25831d5e5b85e4d46644c2c1b6fe00fe0
@@@ -32,7 -32,6 +32,7 @@@
   * 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 "gromacs/pbcutil/ishift.h"
  #include "gromacs/simd/simd.h"
  #include "gromacs/simd/simd_math.h"
  #include "gromacs/simd/vector_operations.h"
@@@ -53,7 -52,7 +53,7 @@@
  
  #include "../nbnxn_kernel_simd_utils.h"
  
- static gmx_inline void
+ static gmx_inline void gmx_simdcall
  gmx_load_simd_2xnn_interactions(int                  excl,
                                  gmx_exclfilter       filter_S0,
                                  gmx_exclfilter       filter_S2,
index 1bf915712b6335d47c728aa40d20108a3423f581,1940d1a3da59269551818bb711c35331bb4ceb3e..32d5554e87bbe797bb616f63c03c08f2c31dd1eb
@@@ -32,7 -32,6 +32,7 @@@
   * 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 "gromacs/pbcutil/ishift.h"
  #include "gromacs/simd/simd.h"
  #include "gromacs/simd/simd_math.h"
  #include "gromacs/simd/vector_operations.h"
@@@ -57,7 -56,7 +57,7 @@@
  
  #include "../nbnxn_kernel_simd_utils.h"
  
- static gmx_inline void
+ static gmx_inline void gmx_simdcall
  gmx_load_simd_4xn_interactions(int gmx_unused             excl,
                                 gmx_exclfilter gmx_unused  filter_S0,
                                 gmx_exclfilter gmx_unused  filter_S1,
index 0cdb28b88548189f02a40f075e454dfb2a0baa0a,a904a2ef52dce09ee00aa647a482c56cb1ebbd51..07f89c5114b987e435cd72fd15c1d5f28b3c122d
@@@ -34,9 -34,9 +34,9 @@@
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
 +
 +#include "config.h"
  
  #include <assert.h>
  #include <math.h>
  #include <sys/time.h>
  #endif
  
 -#include "typedefs.h"
 +#include "gromacs/legacyheaders/typedefs.h"
  #include "gromacs/utility/cstringutil.h"
 -#include "gromacs/utility/smalloc.h"
 -#include "names.h"
 -#include "txtdump.h"
 -#include "pbc.h"
 -#include "chargegroup.h"
 -#include "vec.h"
 -#include "nrnb.h"
 -#include "mshift.h"
 -#include "mdrun.h"
 -#include "sim_util.h"
 -#include "update.h"
 -#include "physics.h"
 -#include "main.h"
 -#include "mdatoms.h"
 -#include "force.h"
 -#include "bondf.h"
 -#include "pme.h"
 -#include "disre.h"
 -#include "orires.h"
 -#include "network.h"
 -#include "calcmu.h"
 -#include "constr.h"
 -#include "xvgr.h"
 -#include "copyrite.h"
 -#include "domdec.h"
 -#include "genborn.h"
 +#include "gromacs/legacyheaders/names.h"
 +#include "gromacs/legacyheaders/txtdump.h"
 +#include "gromacs/pbcutil/pbc.h"
 +#include "gromacs/legacyheaders/chargegroup.h"
 +#include "gromacs/math/vec.h"
 +#include "gromacs/legacyheaders/nrnb.h"
 +#include "gromacs/legacyheaders/mdrun.h"
 +#include "gromacs/legacyheaders/sim_util.h"
 +#include "gromacs/legacyheaders/update.h"
 +#include "gromacs/math/units.h"
 +#include "gromacs/legacyheaders/mdatoms.h"
 +#include "gromacs/legacyheaders/force.h"
 +#include "gromacs/legacyheaders/bondf.h"
 +#include "gromacs/legacyheaders/pme.h"
 +#include "gromacs/legacyheaders/disre.h"
 +#include "gromacs/legacyheaders/orires.h"
 +#include "gromacs/legacyheaders/network.h"
 +#include "gromacs/legacyheaders/calcmu.h"
 +#include "gromacs/legacyheaders/constr.h"
 +#include "gromacs/legacyheaders/copyrite.h"
 +#include "gromacs/legacyheaders/domdec.h"
 +#include "gromacs/legacyheaders/genborn.h"
  #include "nbnxn_atomdata.h"
  #include "nbnxn_search.h"
  #include "nbnxn_kernels/nbnxn_kernel_ref.h"
  #include "nbnxn_kernels/simd_4xn/nbnxn_kernel_simd_4xn.h"
  #include "nbnxn_kernels/simd_2xnn/nbnxn_kernel_simd_2xnn.h"
  #include "nbnxn_kernels/nbnxn_kernel_gpu_ref.h"
 -#include "nonbonded.h"
 +#include "gromacs/legacyheaders/nonbonded.h"
  #include "../gmxlib/nonbonded/nb_kernel.h"
  #include "../gmxlib/nonbonded/nb_free_energy.h"
  
 +#include "gromacs/legacyheaders/types/commrec.h"
 +#include "gromacs/mdlib/nbnxn_cuda/nbnxn_cuda_data_mgmt.h"
 +#include "gromacs/pbcutil/ishift.h"
 +#include "gromacs/pbcutil/mshift.h"
  #include "gromacs/timing/wallcycle.h"
  #include "gromacs/timing/walltime_accounting.h"
  #include "gromacs/utility/gmxmpi.h"
 +#include "gromacs/utility/smalloc.h"
  #include "gromacs/essentialdynamics/edsam.h"
  #include "gromacs/pulling/pull.h"
  #include "gromacs/pulling/pull_rotation.h"
  #include "gromacs/imd/imd.h"
  #include "adress.h"
 -#include "qmmm.h"
 +#include "gromacs/legacyheaders/qmmm.h"
  
 -#include "gmx_omp_nthreads.h"
 +#include "gromacs/legacyheaders/gmx_omp_nthreads.h"
  
 -#include "nbnxn_cuda_data_mgmt.h"
  #include "nbnxn_cuda/nbnxn_cuda.h"
  
 +#include "nb_verlet.h"
 +
  void print_time(FILE                     *out,
                  gmx_walltime_accounting_t walltime_accounting,
                  gmx_int64_t               step,
@@@ -315,7 -313,9 +315,7 @@@ static void calc_virial(int start, int 
      }
  }
  
 -static void posres_wrapper(FILE *fplog,
 -                           int flags,
 -                           gmx_bool bSepDVDL,
 +static void posres_wrapper(int flags,
                             t_inputrec *ir,
                             t_nrnb *nrnb,
                             gmx_localtop_t *top,
                    ir->ePBC == epbcNONE ? NULL : &pbc,
                    lambda[efptRESTRAINT], &dvdl,
                    fr->rc_scaling, fr->ePBC, fr->posres_com, fr->posres_comB);
 -    if (bSepDVDL)
 -    {
 -        gmx_print_sepdvdl(fplog, interaction_function[F_POSRES].longname, v, dvdl);
 -    }
      enerd->term[F_POSRES] += v;
      /* If just the force constant changes, the FEP term is linear,
       * but if k changes, it is not.
@@@ -382,7 -386,9 +382,7 @@@ static void fbposres_wrapper(t_inputre
      inc_nrnb(nrnb, eNR_FBPOSRES, top->idef.il[F_FBPOSRES].nr/2);
  }
  
 -static void pull_potential_wrapper(FILE *fplog,
 -                                   gmx_bool bSepDVDL,
 -                                   t_commrec *cr,
 +static void pull_potential_wrapper(t_commrec *cr,
                                     t_inputrec *ir,
                                     matrix box, rvec x[],
                                     rvec f[],
                                     t_mdatoms *mdatoms,
                                     gmx_enerdata_t *enerd,
                                     real *lambda,
-                                    double t)
+                                    double t,
+                                    gmx_wallcycle_t wcycle)
  {
      t_pbc  pbc;
      real   dvdl;
       * The virial contribution is calculated directly,
       * which is why we call pull_potential after calc_virial.
       */
+     wallcycle_start(wcycle, ewcPULLPOT);
      set_pbc(&pbc, ir->ePBC, box);
      dvdl                     = 0;
      enerd->term[F_COM_PULL] +=
          pull_potential(ir->ePull, ir->pull, mdatoms, &pbc,
                         cr, t, lambda[efptRESTRAINT], x, f, vir_force, &dvdl);
 -    if (bSepDVDL)
 -    {
 -        gmx_print_sepdvdl(fplog, "Com pull", enerd->term[F_COM_PULL], dvdl);
 -    }
      enerd->dvdl_lin[efptRESTRAINT] += dvdl;
+     wallcycle_stop(wcycle, ewcPULLPOT);
  }
  
 -static void pme_receive_force_ener(FILE           *fplog,
 -                                   gmx_bool        bSepDVDL,
 -                                   t_commrec      *cr,
 +static void pme_receive_force_ener(t_commrec      *cr,
                                     gmx_wallcycle_t wcycle,
                                     gmx_enerdata_t *enerd,
                                     t_forcerec     *fr)
      gmx_pme_receive_f(cr, fr->f_novirsum, fr->vir_el_recip, &e_q,
                        fr->vir_lj_recip, &e_lj, &dvdl_q, &dvdl_lj,
                        &cycles_seppme);
 -    if (bSepDVDL)
 -    {
 -        gmx_print_sepdvdl(fplog, "Electrostatic PME mesh", e_q, dvdl_q);
 -        gmx_print_sepdvdl(fplog, "Lennard-Jones PME mesh", e_lj, dvdl_lj);
 -    }
      enerd->term[F_COUL_RECIP] += e_q;
      enerd->term[F_LJ_RECIP]   += e_lj;
      enerd->dvdl_lin[efptCOUL] += dvdl_q;
@@@ -782,11 -802,6 +785,11 @@@ static void do_nb_verlet_fep(nbnxn_pair
      wallcycle_sub_stop(wcycle, ewcsNONBONDED);
  }
  
 +gmx_bool use_GPU(const nonbonded_verlet_t *nbv)
 +{
 +    return nbv != NULL && nbv->bUseGPU;
 +}
 +
  void do_force_cutsVERLET(FILE *fplog, t_commrec *cr,
                           t_inputrec *inputrec,
                           gmx_int64_t step, t_nrnb *nrnb, gmx_wallcycle_t wcycle,
      int                 start, homenr;
      int                 nb_kernel_type;
      double              mu[2*DIM];
 -    gmx_bool            bSepDVDL, bStateChanged, bNS, bFillGrid, bCalcCGCM, bBS;
 +    gmx_bool            bStateChanged, bNS, bFillGrid, bCalcCGCM, bBS;
      gmx_bool            bDoLongRange, bDoForces, bSepLRF, bUseGPU, bUseOrEmulGPU;
      gmx_bool            bDiffKernels = FALSE;
      matrix              boxs;
      start  = 0;
      homenr = mdatoms->homenr;
  
 -    bSepDVDL = (fr->bSepDVDL && do_per_step(step, inputrec->nstlog));
 -
      clear_mat(vir_force);
  
      cg0 = 0;
  
      if ((flags & GMX_FORCE_BONDED) && top->idef.il[F_POSRES].nr > 0)
      {
 -        posres_wrapper(fplog, flags, bSepDVDL, inputrec, nrnb, top, box, x,
 +        posres_wrapper(flags, inputrec, nrnb, top, box, x,
                         enerd, lambda, fr);
      }
  
      }
  
      /* Compute the bonded and non-bonded energies and optionally forces */
 -    do_force_lowlevel(fplog, step, fr, inputrec, &(top->idef),
 +    do_force_lowlevel(fr, inputrec, &(top->idef),
                        cr, nrnb, wcycle, mdatoms,
                        x, hist, f, bSepLRF ? fr->f_twin : f, enerd, fcd, top, fr->born,
                        &(top->atomtypes), bBornRadii, box,
  
      if (inputrec->ePull == epullUMBRELLA || inputrec->ePull == epullCONST_F)
      {
 -        pull_potential_wrapper(fplog, bSepDVDL, cr, inputrec, box, x,
+         /* Since the COM pulling is always done mass-weighted, no forces are
+          * applied to vsites and this call can be done after vsite spreading.
+          */
-                                f, vir_force, mdatoms, enerd, lambda, t);
 +        pull_potential_wrapper(cr, inputrec, box, x,
+                                f, vir_force, mdatoms, enerd, lambda, t,
+                                wcycle);
      }
  
      /* Add the forces from enforced rotation potentials (if any) */
          /* In case of node-splitting, the PP nodes receive the long-range
           * forces, virial and energy from the PME nodes here.
           */
 -        pme_receive_force_ener(fplog, bSepDVDL, cr, wcycle, enerd, fr);
 +        pme_receive_force_ener(cr, wcycle, enerd, fr);
      }
  
      if (bDoForces)
@@@ -1566,7 -1587,7 +1573,7 @@@ void do_force_cutsGROUP(FILE *fplog, t_
      int        cg0, cg1, i, j;
      int        start, homenr;
      double     mu[2*DIM];
 -    gmx_bool   bSepDVDL, bStateChanged, bNS, bFillGrid, bCalcCGCM, bBS;
 +    gmx_bool   bStateChanged, bNS, bFillGrid, bCalcCGCM, bBS;
      gmx_bool   bDoLongRangeNS, bDoForces, bDoPotential, bSepLRF;
      gmx_bool   bDoAdressWF;
      matrix     boxs;
      start  = 0;
      homenr = mdatoms->homenr;
  
 -    bSepDVDL = (fr->bSepDVDL && do_per_step(step, inputrec->nstlog));
 -
      clear_mat(vir_force);
  
      cg0 = 0;
  
      if ((flags & GMX_FORCE_BONDED) && top->idef.il[F_POSRES].nr > 0)
      {
 -        posres_wrapper(fplog, flags, bSepDVDL, inputrec, nrnb, top, box, x,
 +        posres_wrapper(flags, inputrec, nrnb, top, box, x,
                         enerd, lambda, fr);
      }
  
      }
  
      /* Compute the bonded and non-bonded energies and optionally forces */
 -    do_force_lowlevel(fplog, step, fr, inputrec, &(top->idef),
 +    do_force_lowlevel(fr, inputrec, &(top->idef),
                        cr, nrnb, wcycle, mdatoms,
                        x, hist, f, bSepLRF ? fr->f_twin : f, enerd, fcd, top, fr->born,
                        &(top->atomtypes), bBornRadii, box,
  
      if (inputrec->ePull == epullUMBRELLA || inputrec->ePull == epullCONST_F)
      {
 -        pull_potential_wrapper(fplog, bSepDVDL, cr, inputrec, box, x,
 +        pull_potential_wrapper(cr, inputrec, box, x,
-                                f, vir_force, mdatoms, enerd, lambda, t);
+                                f, vir_force, mdatoms, enerd, lambda, t,
+                                wcycle);
      }
  
      /* Add the forces from enforced rotation potentials (if any) */
          /* In case of node-splitting, the PP nodes receive the long-range
           * forces, virial and energy from the PME nodes here.
           */
 -        pme_receive_force_ener(fplog, bSepDVDL, cr, wcycle, enerd, fr);
 +        pme_receive_force_ener(cr, wcycle, enerd, fr);
      }
  
      if (bDoForces)
@@@ -2421,8 -2445,8 +2429,8 @@@ void calc_enervirdiff(FILE *fplog, int 
      }
  }
  
 -void calc_dispcorr(FILE *fplog, t_inputrec *ir, t_forcerec *fr,
 -                   gmx_int64_t step, int natoms,
 +void calc_dispcorr(t_inputrec *ir, t_forcerec *fr,
 +                   int natoms,
                     matrix box, real lambda, tensor pres, tensor virial,
                     real *prescorr, real *enercorr, real *dvdlcorr)
  {
              }
          }
  
 -        if (fr->bSepDVDL && do_per_step(step, ir->nstlog))
 -        {
 -            gmx_print_sepdvdl(fplog, "Dispersion correction", *enercorr, dvdlambda);
 -        }
          if (fr->efep != efepNO)
          {
              *dvdlcorr += dvdlambda;
@@@ -2627,7 -2655,7 +2635,7 @@@ void finish_run(FILE *fplog, t_commrec 
                  t_inputrec *inputrec,
                  t_nrnb nrnb[], gmx_wallcycle_t wcycle,
                  gmx_walltime_accounting_t walltime_accounting,
 -                wallclock_gpu_t *gputimes,
 +                nonbonded_verlet_t *nbv,
                  gmx_bool bWriteStat)
  {
      int     i, j;
  
      if (SIMMASTER(cr))
      {
 +        wallclock_gpu_t* gputimes = use_GPU(nbv) ?
 +            nbnxn_cuda_get_timings(nbv->cu_nbv) : NULL;
          wallcycle_print(fplog, cr->nnodes, cr->npmenodes,
                          elapsed_time_over_all_ranks,
                          wcycle, gputimes);
index 8561506e9aea6de8e1f587f0e37e9692c462e0d3,787135f7158cd12b23bac96a7446d7de8d8e44a7..8287d12c58af388a91eb92b1fd1512f03c5a9bb5
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
 +
 +#include "config.h"
  
  
  #include <stdio.h>
  #include <math.h>
  
 -#include "types/commrec.h"
 -#include "sysstuff.h"
 -#include "gromacs/utility/smalloc.h"
 -#include "typedefs.h"
 -#include "nrnb.h"
 -#include "physics.h"
 -#include "macros.h"
 -#include "vec.h"
 -#include "main.h"
 -#include "update.h"
 +#include "gromacs/legacyheaders/types/commrec.h"
 +#include "gromacs/legacyheaders/typedefs.h"
 +#include "gromacs/legacyheaders/nrnb.h"
 +#include "gromacs/math/units.h"
 +#include "gromacs/legacyheaders/macros.h"
 +#include "gromacs/math/vec.h"
 +#include "gromacs/legacyheaders/update.h"
  #include "gromacs/random/random.h"
 -#include "mshift.h"
 -#include "tgroup.h"
 -#include "force.h"
 -#include "names.h"
 -#include "txtdump.h"
 -#include "mdrun.h"
 -#include "constr.h"
 -#include "disre.h"
 -#include "orires.h"
 -#include "gmx_omp_nthreads.h"
 +#include "gromacs/legacyheaders/tgroup.h"
 +#include "gromacs/legacyheaders/force.h"
 +#include "gromacs/legacyheaders/names.h"
 +#include "gromacs/legacyheaders/txtdump.h"
 +#include "gromacs/legacyheaders/mdrun.h"
 +#include "gromacs/legacyheaders/constr.h"
 +#include "gromacs/legacyheaders/disre.h"
 +#include "gromacs/legacyheaders/orires.h"
 +#include "gromacs/legacyheaders/gmx_omp_nthreads.h"
  
  #include "gromacs/fileio/confio.h"
 -#include "gromacs/fileio/futil.h"
 +#include "gromacs/pbcutil/mshift.h"
 +#include "gromacs/pbcutil/pbc.h"
 +#include "gromacs/pulling/pull.h"
  #include "gromacs/timing/wallcycle.h"
 +#include "gromacs/utility/futil.h"
  #include "gromacs/utility/gmxomp.h"
 -#include "gromacs/pulling/pull.h"
 +#include "gromacs/utility/smalloc.h"
  
  /*For debugging, start at v(-dt/2) for velolcity verlet -- uncomment next line */
  /*#define STARTFROMDT2*/
@@@ -1317,7 -1318,7 +1317,7 @@@ static void deform(gmx_update_t upd
          x[i][YY] = mu[YY][YY]*x[i][YY]+mu[ZZ][YY]*x[i][ZZ];
          x[i][ZZ] = mu[ZZ][ZZ]*x[i][ZZ];
      }
-     if (*scale_tot)
+     if (scale_tot != NULL)
      {
          /* The transposes of the scaling matrices are stored,
           * so we need to do matrix multiplication in the inverse order.
@@@ -1662,6 -1663,7 +1662,7 @@@ void update_constraints(FIL
  
      if (inputrec->eI == eiSD1 && bDoConstr && !bFirstHalf)
      {
+         wallcycle_start(wcycle, ewcUPDATE);
          xprime = get_xprime(state, upd);
  
          nth = gmx_omp_nthreads_get(emntUpdate);
                            DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
          }
          inc_nrnb(nrnb, eNR_UPDATE, homenr);
+         wallcycle_stop(wcycle, ewcUPDATE);
  
          if (bDoConstr)
          {
  
      if ((inputrec->eI == eiSD2) && !(bFirstHalf))
      {
+         wallcycle_start(wcycle, ewcUPDATE);
          xprime = get_xprime(state, upd);
  
          nth = gmx_omp_nthreads_get(emntUpdate);
                            DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
          }
          inc_nrnb(nrnb, eNR_UPDATE, homenr);
+         wallcycle_stop(wcycle, ewcUPDATE);
  
          if (bDoConstr)
          {
index bfadaa93e0b9c7e20cabd3ee82513b97f3b59e5a,458a2fb4723fd345c99a356966ebc42fea1e33cf..1e084858bbb7a117025d75f25ccf1eefe39c07dc
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
  
 +#include "config.h"
  
  #include <math.h>
  #include <stdio.h>
  #include <stdlib.h>
 -#include "gromacs/fileio/futil.h"
 -#include "index.h"
 -#include "gromacs/fileio/gmxfio.h"
 -#include "vec.h"
 -#include "typedefs.h"
 -#include "types/commrec.h"
 -#include "network.h"
 -#include "gromacs/fileio/filenm.h"
  #include <string.h>
 -#include "gromacs/utility/smalloc.h"
 +
 +#include "gromacs/utility/futil.h"
 +#include "gromacs/legacyheaders/typedefs.h"
 +#include "gromacs/legacyheaders/types/commrec.h"
 +#include "gromacs/legacyheaders/network.h"
  #include "pull.h"
 -#include "xvgr.h"
 -#include "names.h"
 -#include "pbc.h"
 -#include "mtop_util.h"
 -#include "mdrun.h"
 -#include "gmx_ga2la.h"
 -#include "copyrite.h"
 -#include "macros.h"
 -#include "vec.h"
 +#include "gromacs/legacyheaders/names.h"
 +#include "gromacs/pbcutil/pbc.h"
 +#include "gromacs/topology/mtop_util.h"
 +#include "gromacs/legacyheaders/mdrun.h"
 +#include "gromacs/legacyheaders/gmx_ga2la.h"
 +#include "gromacs/legacyheaders/copyrite.h"
 +#include "gromacs/legacyheaders/macros.h"
 +
 +#include "gromacs/fileio/filenm.h"
 +#include "gromacs/fileio/gmxfio.h"
 +#include "gromacs/fileio/xvgr.h"
 +#include "gromacs/math/vec.h"
 +#include "gromacs/utility/smalloc.h"
  
  static void pull_print_group_x(FILE *out, ivec dim, const t_pull_group *pgrp)
  {
@@@ -179,7 -180,7 +179,7 @@@ static FILE *open_pull_out(const char *
                          if (pull->dim[m])
                          {
                              sprintf(buf, "%d %s%c", c+1, "c", 'X'+m);
 -                            setname[nsets] = strdup(buf);
 +                            setname[nsets] = gmx_strdup(buf);
                              nsets++;
                          }
                      }
                      if (pull->dim[m])
                      {
                          sprintf(buf, "%d %s%c", c+1, "d", 'X'+m);
 -                        setname[nsets] = strdup(buf);
 +                        setname[nsets] = gmx_strdup(buf);
                          nsets++;
                      }
                  }
              else
              {
                  sprintf(buf, "%d", c+1);
 -                setname[nsets] = strdup(buf);
 +                setname[nsets] = gmx_strdup(buf);
                  nsets++;
              }
          }
@@@ -501,6 -502,11 +501,11 @@@ static void do_constraint(t_pull *pull
                  r_ij[c][m] = a*pull->coord[c].vec[m];
              }
          }
+         if (dnorm2(r_ij[c]) == 0)
+         {
+             gmx_fatal(FARGS, "Distance for pull coordinate %d is zero with constraint pulling, which is not allowed.", c + 1);
+         }
      }
  
      bConverged_all = FALSE;
              double f_invr;
  
              /* Add the pull contribution to the virial */
+             /* We have already checked above that r_ij[c] != 0 */
              f_invr = pcrd->f_scal/dnorm(r_ij[c]);
  
              for (j = 0; j < DIM; j++)
@@@ -784,7 -791,19 +790,19 @@@ static void do_pull_pot(int ePull
          {
              case epullgDIST:
                  ndr   = dnorm(pcrd->dr);
-                 invdr = 1/ndr;
+                 if (ndr > 0)
+                 {
+                     invdr = 1/ndr;
+                 }
+                 else
+                 {
+                     /* With an harmonic umbrella, the force is 0 at r=0,
+                      * so we can set invdr to any value.
+                      * With a constant force, the force at r=0 is not defined,
+                      * so we zero it (this is anyhow a very rare event).
+                      */
+                     invdr = 0;
+                 }
                  if (ePull == epullUMBRELLA)
                  {
                      pcrd->f_scal  =       -k*dev;
@@@ -931,6 -950,9 +949,9 @@@ void dd_make_local_pull_groups(gmx_domd
          make_local_pull_group(ga2la, &pull->group[g],
                                0, md->homenr);
      }
+     /* Since the PBC of atoms might have changed, we need to update the PBC */
+     pull->bSetPBCatoms = TRUE;
  }
  
  static void init_pull_group_index(FILE *fplog, t_commrec *cr,
@@@ -1242,6 -1264,9 +1263,9 @@@ void init_pull(FILE *fplog, t_inputrec 
          snew(pull->dyna, pull->ncoord);
      }
  
+     /* We still need to initialize the PBC reference coordinates */
+     pull->bSetPBCatoms = TRUE;
      /* Only do I/O when we are doing dynamics and if we are the MASTER */
      pull->out_x = NULL;
      pull->out_f = NULL;
index 97287aa708b0d218d1a6ee91d9e987e786a15ea7,19e762346c77e98eddfd8ea64a0d285b859b0662..3d90b1ae9c8aa6af93414d2510bef57a05a7a6f9
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
 +
 +#include "config.h"
  
  #include <stdlib.h>
  
 -#include "sysstuff.h"
 -#include "princ.h"
 -#include "gromacs/fileio/futil.h"
 -#include "vec.h"
 +#include "gromacs/utility/futil.h"
 +#include "gromacs/math/vec.h"
  #include "gromacs/utility/smalloc.h"
 -#include "typedefs.h"
 -#include "types/commrec.h"
 -#include "names.h"
 -#include "gmx_fatal.h"
 -#include "macros.h"
 -#include "symtab.h"
 -#include "index.h"
 +#include "gromacs/legacyheaders/typedefs.h"
 +#include "gromacs/legacyheaders/types/commrec.h"
 +#include "gromacs/legacyheaders/names.h"
 +#include "gromacs/utility/fatalerror.h"
 +#include "gromacs/legacyheaders/macros.h"
  #include "gromacs/fileio/confio.h"
 -#include "network.h"
 -#include "pbc.h"
 +#include "gromacs/legacyheaders/network.h"
 +#include "gromacs/pbcutil/pbc.h"
  #include "pull.h"
 -#include "gmx_ga2la.h"
 +#include "gromacs/legacyheaders/gmx_ga2la.h"
  
  static void pull_set_pbcatom(t_commrec *cr, t_pull_group *pgrp,
-                              t_mdatoms *md, rvec *x,
+                              rvec *x,
                               rvec x_pbc)
  {
      int a, m;
  
-     if (cr && PAR(cr))
+     if (cr != NULL && DOMAINDECOMP(cr))
      {
-         if (DOMAINDECOMP(cr))
-         {
-             if (!ga2la_get_home(cr->dd->ga2la, pgrp->pbcatom, &a))
-             {
-                 a = -1;
-             }
-         }
-         else
-         {
-             a = pgrp->pbcatom;
-         }
-         if (a >= 0 && a < md->homenr)
+         if (ga2la_get_home(cr->dd->ga2la, pgrp->pbcatom, &a))
          {
              copy_rvec(x[a], x_pbc);
          }
@@@ -90,7 -82,7 +78,7 @@@
  }
  
  static void pull_set_pbcatoms(t_commrec *cr, t_pull *pull,
-                               t_mdatoms *md, rvec *x,
+                               rvec *x,
                                rvec *x_pbc)
  {
      int g, n, m;
          }
          else
          {
-             pull_set_pbcatom(cr, &pull->group[g], md, x, x_pbc[g]);
+             pull_set_pbcatom(cr, &pull->group[g], x, x_pbc[g]);
              for (m = 0; m < DIM; m++)
              {
                  if (pull->dim[m] == 0)
@@@ -314,9 -306,21 +302,21 @@@ void pull_calc_coms(t_commrec *cr
          snew(pull->dbuf, 3*pull->ngroup);
      }
  
-     if (pull->bRefAt)
+     if (pull->bRefAt && pull->bSetPBCatoms)
      {
-         pull_set_pbcatoms(cr, pull, md, x, pull->rbuf);
+         pull_set_pbcatoms(cr, pull, x, pull->rbuf);
+         if (cr != NULL && DOMAINDECOMP(cr))
+         {
+             /* We can keep these PBC reference coordinates fixed for nstlist
+              * steps, since atoms won't jump over PBC.
+              * This avoids a global reduction at the next nstlist-1 steps.
+              * Note that the exact values of the pbc reference coordinates
+              * are irrelevant, as long all atoms in the group are within
+              * half a box distance of the reference coordinate.
+              */
+             pull->bSetPBCatoms = FALSE;
+         }
      }
  
      if (pull->cosdim >= 0)
index ca91e29742d56c6d3b8ede5bd184f94df2808f7c,ae8dfac457299a14ab0ce4430c0f3766757eba35..5f841a1a7527f0b80572defbcbd8d77fe41d22ba
@@@ -3,7 -3,7 +3,7 @@@
  // Required before flex definitions, since it includes <stdint.h>.
  // Otherwise, compilers not strictly C99 get macro redefinition errors,
  // since flex defines INT32_MAX etc. in such cases.
 -#include "gromacs/legacyheaders/types/simple.h"
 +#include "gromacs/utility/basedefinitions.h"
  
  
  
@@@ -331,7 -331,7 +331,7 @@@ void _gmx_sel_yyfree (void * ,yyscan_t 
  
  #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
  
- #define _gmx_sel_yywrap(yyscanner) 1
+ static inline int _gmx_sel_yywrap(yyscan_t yyscanner) { return 1; }
  #define YY_SKIP_YYWRAP
  
  typedef unsigned char YY_CHAR;
@@@ -548,11 -548,15 +548,15 @@@ static yyconst flex_int16_t yy_chk[151
  // this call.
  #define ADD_TOKEN _gmx_sel_lexer_add_token(yytext, yyleng, state)
  
+ // Set YY_BREAK to an empty value to avoid warnings (for the PGI compiler)
+ // when we have return statements followed by break. Instead, we add breaks
+ // manually.
+ #define YY_BREAK
  #define YY_NO_UNISTD_H 1
  
  
  
- #line 556 "scanner.cpp"
+ #line 560 "scanner.cpp"
  
  #define INITIAL 0
  #define matchof 1
@@@ -780,7 -784,7 +784,7 @@@ YY_DEC
        register int yy_act;
      struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
  
- #line 90 "scanner.l"
+ #line 94 "scanner.l"
  
  
  
      }
  
  
- #line 818 "scanner.cpp"
+ #line 822 "scanner.cpp"
  
        if ( !yyg->yy_init )
                {
@@@ -895,34 -899,34 +899,34 @@@ do_action:      /* This label is used only t
  
  case 1:
  YY_RULE_SETUP
- #line 123 "scanner.l"
+ #line 127 "scanner.l"
+ break;
        YY_BREAK
  case 2:
  YY_RULE_SETUP
- #line 124 "scanner.l"
+ #line 128 "scanner.l"
  { yylval->i   = strtol(yytext, NULL, 10);    ADD_TOKEN; return TOK_INT; }
        YY_BREAK
  case 3:
  YY_RULE_SETUP
- #line 125 "scanner.l"
+ #line 129 "scanner.l"
  { yylval->r   = strtod(yytext, NULL);        ADD_TOKEN; return TOK_REAL; }
        YY_BREAK
  case 4:
  YY_RULE_SETUP
- #line 126 "scanner.l"
+ #line 130 "scanner.l"
  { yylval->str = gmx_strndup(yytext+1, yyleng-2); ADD_TOKEN; return STR;  }
        YY_BREAK
  case 5:
  /* rule 5 can match eol */
  YY_RULE_SETUP
- #line 128 "scanner.l"
- { _gmx_sel_lexer_add_token(" ", 1, state); }
+ #line 132 "scanner.l"
+ { _gmx_sel_lexer_add_token(" ", 1, state); break; }
        YY_BREAK
  case 6:
  /* rule 6 can match eol */
  YY_RULE_SETUP
- #line 129 "scanner.l"
+ #line 133 "scanner.l"
  {
                      if (yytext[0] == ';' || state->bInteractive)
                      {
                      {
                          _gmx_sel_lexer_add_token(" ", 1, state);
                      }
+                     break;
                  }
        YY_BREAK
  case YY_STATE_EOF(cmdstart):
- #line 142 "scanner.l"
+ #line 147 "scanner.l"
  { state->bCmdStart = true; yyterminate(); }
        YY_BREAK
  case YY_STATE_EOF(INITIAL):
  case YY_STATE_EOF(matchof):
  case YY_STATE_EOF(matchbool):
- #line 143 "scanner.l"
+ #line 148 "scanner.l"
  { state->bCmdStart = true; return CMD_SEP; }
        YY_BREAK
  
  case 7:
  YY_RULE_SETUP
- #line 146 "scanner.l"
+ #line 151 "scanner.l"
  { ADD_TOKEN; yylval->i = 1; return TOK_INT; }
        YY_BREAK
  case 8:
  YY_RULE_SETUP
- #line 147 "scanner.l"
+ #line 152 "scanner.l"
  { ADD_TOKEN; yylval->i = 0; return TOK_INT; }
        YY_BREAK
  
  case 9:
  YY_RULE_SETUP
- #line 149 "scanner.l"
+ #line 154 "scanner.l"
  { ADD_TOKEN; return GROUP; }
        YY_BREAK
  case 10:
  YY_RULE_SETUP
- #line 150 "scanner.l"
+ #line 155 "scanner.l"
  { ADD_TOKEN; return TO; }
        YY_BREAK
  case 11:
  YY_RULE_SETUP
- #line 151 "scanner.l"
+ #line 156 "scanner.l"
  { ADD_TOKEN; BEGIN(0); return OF; }
        YY_BREAK
  case 12:
  YY_RULE_SETUP
- #line 152 "scanner.l"
+ #line 157 "scanner.l"
  { ADD_TOKEN; return AND; }
        YY_BREAK
  case 13:
  YY_RULE_SETUP
- #line 153 "scanner.l"
+ #line 158 "scanner.l"
  { ADD_TOKEN; return OR; }
        YY_BREAK
  case 14:
  YY_RULE_SETUP
- #line 154 "scanner.l"
+ #line 159 "scanner.l"
  { ADD_TOKEN; return XOR; }
        YY_BREAK
  case 15:
  YY_RULE_SETUP
- #line 155 "scanner.l"
+ #line 160 "scanner.l"
  { ADD_TOKEN; return NOT; }
        YY_BREAK
  case 16:
  YY_RULE_SETUP
- #line 156 "scanner.l"
+ #line 161 "scanner.l"
  { yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return CMP_OP; }
        YY_BREAK
  case 17:
  YY_RULE_SETUP
- #line 158 "scanner.l"
+ #line 163 "scanner.l"
  { return _gmx_sel_lexer_process_identifier(yylval, yytext, yyleng, state); }
        YY_BREAK
  case 18:
  /* rule 18 can match eol */
  YY_RULE_SETUP
- #line 160 "scanner.l"
- { _gmx_sel_lexer_add_token(" ", 1, state); }
+ #line 165 "scanner.l"
+ { _gmx_sel_lexer_add_token(" ", 1, state); break; }
        YY_BREAK
  case 19:
  YY_RULE_SETUP
- #line 161 "scanner.l"
+ #line 166 "scanner.l"
  { yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return STR; }
        YY_BREAK
  case 20:
  YY_RULE_SETUP
- #line 162 "scanner.l"
+ #line 167 "scanner.l"
  { ADD_TOKEN; return yytext[0]; }
        YY_BREAK
  case 21:
  YY_RULE_SETUP
- #line 163 "scanner.l"
+ #line 168 "scanner.l"
  YY_FATAL_ERROR( "flex scanner jammed" );
        YY_BREAK
- #line 1028 "scanner.cpp"
+ #line 1033 "scanner.cpp"
  
        case YY_END_OF_BUFFER:
                {
@@@ -2175,4 -2180,4 +2180,4 @@@ void _gmx_sel_yyfree (void * ptr , yysc
  
  #define YYTABLES_NAME "yytables"
  
- #line 163 "scanner.l"
+ #line 168 "scanner.l"
index abbeb04d6c8e96571b1cc30e1598bcf6dfe84d36,2ba3ccd0f386715f8145f1303ed018ea4cbfeb38..57e365442e7a583690937cd1252508f1082206ff
@@@ -50,7 -50,7 +50,7 @@@
  // Required before flex definitions, since it includes <stdint.h>.
  // Otherwise, compilers not strictly C99 get macro redefinition errors,
  // since flex defines INT32_MAX etc. in such cases.
 -#include "gromacs/legacyheaders/types/simple.h"
 +#include "gromacs/utility/basedefinitions.h"
  }
  %{
  #include "gromacs/utility/cstringutil.h"
  // this call.
  #define ADD_TOKEN _gmx_sel_lexer_add_token(yytext, yyleng, state)
  
+ // Set YY_BREAK to an empty value to avoid warnings (for the PGI compiler)
+ // when we have return statements followed by break. Instead, we add breaks
+ // manually.
+ #define YY_BREAK
  %}
  
  INTEGER    [[:digit:]]+
@@@ -120,12 -124,12 +124,12 @@@ COMMENT    (#.*
      }
  %}
  
- {COMMENT}
+ {COMMENT}       break;
  {INTEGER}       { yylval->i   = strtol(yytext, NULL, 10);    ADD_TOKEN; return TOK_INT; }
  {REAL}          { yylval->r   = strtod(yytext, NULL);        ADD_TOKEN; return TOK_REAL; }
  {STRING}        { yylval->str = gmx_strndup(yytext+1, yyleng-2); ADD_TOKEN; return STR;  }
  
- \\\n            { _gmx_sel_lexer_add_token(" ", 1, state); }
+ \\\n            { _gmx_sel_lexer_add_token(" ", 1, state); break; }
  ";"|\n          {
                      if (yytext[0] == ';' || state->bInteractive)
                      {
                      {
                          _gmx_sel_lexer_add_token(" ", 1, state);
                      }
+                     break;
                  }
  
  <cmdstart><<EOF>> { state->bCmdStart = true; yyterminate(); }
@@@ -157,6 -162,6 +162,6 @@@ not|"!"         { ADD_TOKEN; return NOT
  
  {IDENTIFIER}    { return _gmx_sel_lexer_process_identifier(yylval, yytext, yyleng, state); }
  
- [[:space:]]+    { _gmx_sel_lexer_add_token(" ", 1, state); }
+ [[:space:]]+    { _gmx_sel_lexer_add_token(" ", 1, state); break; }
  [_[:alnum:]]+   { yylval->str = gmx_strndup(yytext, yyleng); ADD_TOKEN; return STR; }
  .               { ADD_TOKEN; return yytext[0]; }
index 266196db102c00c09eeba016581440bf6e498487,6dc819f879bc9f58114c477b2e45efce27e74db7..482cca2f6f5ce4f979b08d33d580b29fec24134a
@@@ -7,7 -7,7 +7,7 @@@
  // Required before flex definitions, since it includes <stdint.h>.
  // Otherwise, compilers not strictly C99 get macro redefinition errors,
  // since flex defines INT32_MAX etc. in such cases.
 -#include "gromacs/legacyheaders/types/simple.h"
 +#include "gromacs/utility/basedefinitions.h"
  
  
  
@@@ -340,7 -340,7 +340,7 @@@ extern int _gmx_sel_yylex (yyscan_t yys
  #undef YY_DECL
  #endif
  
- #line 163 "scanner.l"
+ #line 168 "scanner.l"
  
  #line 346 "scanner_flex.h"
  #undef _gmx_sel_yyIN_HEADER
index ce4114854fcd646394a262c44b88c4ebcc57b13e,fc5ce923133c7a0f64684a86b6eb098ed41dcb4d..d7feb7d042ee8b56cd20db6af7d68119b9567926
   * \ingroup module_selection
   * \endcond
   */
 +#include "gmxpre.h"
 +
  #include <stdlib.h>
  #include <string.h>
  
  #include <string>
  
 -#include "gromacs/legacyheaders/typedefs.h"
 -
  #include "gromacs/utility/cstringutil.h"
  #include "gromacs/utility/exceptions.h"
  #include "gromacs/utility/gmxassert.h"
@@@ -104,7 -104,7 +104,7 @@@ init_param_token(YYSTYPE *yylval, gmx_a
      }
      else
      {
 -        yylval->str = param->name ? strdup(param->name) : NULL;
 +        yylval->str = param->name ? gmx_strdup(param->name) : NULL;
      }
      return PARAM;
  }
@@@ -324,8 -324,7 +324,7 @@@ _gmx_sel_lexer_process_identifier(YYSTY
                  GMX_THROW(gmx::InternalError("Unsupported variable type"));
                  return INVALID;
          }
-         delete yylval->sel;
-         return INVALID; /* Should not be reached. */
+         /* This position should not be reached. */
      }
      /* For method symbols, return the correct type */
      if (symtype == gmx::SelectionParserSymbol::MethodSymbol)
      if (symtype == gmx::SelectionParserSymbol::PositionSymbol)
      {
          state->bMatchOf    = true;
 -        yylval->str        = strdup(symbol->name().c_str());
 +        yylval->str        = gmx_strdup(symbol->name().c_str());
          state->prev_pos_kw = 2;
          return KEYWORD_POS;
      }
index c52adbd7697951996cae227501697a65fc8029d7,c667739d5ec409017bb6299600c1a374351e0185..367737e3389a57a7834b3cb6ff62126ff8276a59
@@@ -39,8 -39,6 +39,8 @@@
   * \author Teemu Murtola <teemu.murtola@gmail.com>
   * \ingroup module_selection
   */
 +#include "gmxpre.h"
 +
  #include <cstring>
  
  #include "gromacs/selection/indexutil.h"
  const char *
  _gmx_selelem_type_str(const gmx::SelectionTreeElement &sel)
  {
+     const char *p = NULL;
      switch (sel.type)
      {
-         case SEL_CONST:      return "CONST";
-         case SEL_EXPRESSION: return "EXPR";
-         case SEL_BOOLEAN:    return "BOOL";
-         case SEL_ARITHMETIC: return "ARITH";
-         case SEL_ROOT:       return "ROOT";
-         case SEL_SUBEXPR:    return "SUBEXPR";
-         case SEL_SUBEXPRREF: return "REF";
-         case SEL_GROUPREF:   return "GROUPREF";
-         case SEL_MODIFIER:   return "MODIFIER";
+         case SEL_CONST:      p = "CONST";    break;
+         case SEL_EXPRESSION: p = "EXPR";     break;
+         case SEL_BOOLEAN:    p = "BOOL";     break;
+         case SEL_ARITHMETIC: p = "ARITH";    break;
+         case SEL_ROOT:       p = "ROOT";     break;
+         case SEL_SUBEXPR:    p = "SUBEXPR";  break;
+         case SEL_SUBEXPRREF: p = "REF";      break;
+         case SEL_GROUPREF:   p = "GROUPREF"; break;
+         case SEL_MODIFIER:   p = "MODIFIER"; break;
+             // No default clause so we intentionally get compiler errors
+             // if new selection choices are added later.
      }
-     return NULL;
+     return p;
  }
  
  /*!
  const char *
  _gmx_sel_value_type_str(const gmx_ana_selvalue_t *val)
  {
+     const char *p = NULL;
      switch (val->type)
      {
-         case NO_VALUE:       return "NONE";
-         case INT_VALUE:      return "INT";
-         case REAL_VALUE:     return "REAL";
-         case STR_VALUE:      return "STR";
-         case POS_VALUE:      return "VEC";
-         case GROUP_VALUE:    return "GROUP";
+         case NO_VALUE:       p = "NONE";  break;
+         case INT_VALUE:      p = "INT";   break;
+         case REAL_VALUE:     p = "REAL";  break;
+         case STR_VALUE:      p = "STR";   break;
+         case POS_VALUE:      p = "VEC";   break;
+         case GROUP_VALUE:    p = "GROUP"; break;
+             // No default clause so we intentionally get compiler errors
+             // if new selection choices are added later.
      }
-     return NULL;
+     return p;
  }
  
  /*! \copydoc _gmx_selelem_type_str() */
  const char *
  _gmx_selelem_boolean_type_str(const gmx::SelectionTreeElement &sel)
  {
+     const char *p = NULL;
      switch (sel.u.boolt)
      {
-         case BOOL_NOT:  return "NOT"; break;
-         case BOOL_AND:  return "AND"; break;
-         case BOOL_OR:   return "OR";  break;
-         case BOOL_XOR:  return "XOR"; break;
+         case BOOL_NOT:  p = "NOT"; break;
+         case BOOL_AND:  p = "AND"; break;
+         case BOOL_OR:   p = "OR";  break;
+         case BOOL_XOR:  p = "XOR"; break;
+             // No default clause so we intentionally get compiler errors
+             // if new selection choices are added later.
      }
-     return NULL;
+     return p;
  }
  
  
@@@ -368,8 -375,7 +377,8 @@@ void SelectionTreeElement::checkUnsorte
      }
  }
  
 -void SelectionTreeElement::resolveIndexGroupReference(gmx_ana_indexgrps_t *grps)
 +void SelectionTreeElement::resolveIndexGroupReference(
 +        gmx_ana_indexgrps_t *grps, int natoms)
  {
      GMX_RELEASE_ASSERT(type == SEL_GROUPREF,
                         "Should only be called for index group reference elements");
      gmx_ana_index_set(&u.cgrp, foundGroup.isize, foundGroup.index,
                        foundGroup.nalloc_index);
      setName(foundName);
 +
 +    if (natoms > 0)
 +    {
 +        checkIndexGroup(natoms);
 +    }
 +}
 +
 +void SelectionTreeElement::checkIndexGroup(int natoms)
 +{
 +    GMX_RELEASE_ASSERT(type == SEL_CONST && v.type == GROUP_VALUE,
 +                       "Should only be called for index group elements");
 +    if (!gmx_ana_index_check_range(&u.cgrp, natoms))
 +    {
 +        std::string message = formatString(
 +                    "Group '%s' cannot be used in selections, because it "
 +                    "contains negative atom indices and/or references atoms "
 +                    "not present (largest allowed atom index is %d).",
 +                    name().c_str(), natoms);
 +        GMX_THROW(InconsistentInputError(message));
 +    }
  }
  
  } // namespace gmx
index 8e4af8ba70739c643b6d9b1dd69a9efb2b87b6f1,605bf1cf2df658761e09b9b70fe608319a885dc6..5ff24d7423257fcf202f56e770a027e0b81c7590
@@@ -39,8 -39,6 +39,8 @@@
   * \author Teemu Murtola <teemu.murtola@gmail.com>
   * \ingroup module_selection
   */
 +#include "gmxpre.h"
 +
  #include <cmath>
  
  #include "gromacs/legacyheaders/macros.h"
@@@ -199,17 -197,20 +199,20 @@@ comparison_type(char *str
  static const char *
  comparison_type_str(e_comparison_t cmpt)
  {
+     const char *p = NULL;
      switch (cmpt)
      {
-         case CMP_INVALID: return "INVALID"; break;
-         case CMP_LESS:    return "<";  break;
-         case CMP_LEQ:     return "<="; break;
-         case CMP_GTR:     return ">";  break;
-         case CMP_GEQ:     return ">="; break;
-         case CMP_EQUAL:   return "=="; break;
-         case CMP_NEQ:     return "!="; break;
+         case CMP_INVALID: p = "INVALID"; break;
+         case CMP_LESS:    p = "<";       break;
+         case CMP_LEQ:     p = "<=";      break;
+         case CMP_GTR:     p = ">";       break;
+         case CMP_GEQ:     p = ">=";      break;
+         case CMP_EQUAL:   p = "==";      break;
+         case CMP_NEQ:     p = "!=";      break;
+             // No default clause so we intentionally get compiler errors
+             // if new selection choices are added later.
      }
-     return NULL;
+     return p;
  }
  
  /*!
index 06601be1e4d1f9c1593bb107210f7e3b42cb5824,177913fad1212ed2c34808fe16dd744b31b516ef..1d89772d2a197883fb94864b6cec07c1390821da
   * \author Teemu Murtola <teemu.murtola@gmail.com>
   * \ingroup module_selection
   */
 +#include "gmxpre.h"
 +
 +#include "gromacs/selection/nbsearch.h"
 +
  #include <gtest/gtest.h>
  
  #include <cmath>
  
 +#include <algorithm>
  #include <limits>
 -#include <set>
 +#include <numeric>
  #include <vector>
  
 -#include "gromacs/legacyheaders/pbc.h"
 -#include "gromacs/legacyheaders/vec.h"
 -
 -#include "gromacs/selection/nbsearch.h"
 +#include "gromacs/math/vec.h"
 +#include "gromacs/pbcutil/pbc.h"
  #include "gromacs/random/random.h"
 +#include "gromacs/topology/block.h"
  #include "gromacs/utility/smalloc.h"
  
  #include "testutils/testasserts.h"
@@@ -75,47 -71,19 +75,43 @@@ namespac
  class NeighborhoodSearchTestData
  {
      public:
 +        struct RefPair
 +        {
 +            RefPair(int refIndex, real distance)
 +                : refIndex(refIndex), distance(distance), bFound(false),
 +                  bExcluded(false)
 +            {
 +            }
 +
 +            bool operator<(const RefPair &other) const
 +            {
 +                return refIndex < other.refIndex;
 +            }
 +
 +            int                 refIndex;
 +            real                distance;
 +            // The variables below are state variables that are only used
 +            // during the actual testing after creating a copy of the reference
 +            // pair list, not as part of the reference data.
 +            // Simpler to have just a single structure for both purposes.
 +            bool                bFound;
 +            bool                bExcluded;
 +        };
 +
          struct TestPosition
          {
-             TestPosition() : refMinDist(0.0), refNearestPoint(-1)
-             {
-                 clear_rvec(x);
-             }
              explicit TestPosition(const rvec x)
                  : refMinDist(0.0), refNearestPoint(-1)
              {
                  copy_rvec(x, this->x);
              }
  
 -            rvec                x;
 -            real                refMinDist;
 -            int                 refNearestPoint;
 -            std::set<int>       refPairs;
 +            rvec                 x;
 +            real                 refMinDist;
 +            int                  refNearestPoint;
 +            std::vector<RefPair> refPairs;
          };
 +
          typedef std::vector<TestPosition> TestPositionList;
  
          NeighborhoodSearchTestData(int seed, real cutoff);
          void generateRandomPosition(rvec x);
          void generateRandomRefPositions(int count);
          void generateRandomTestPositions(int count);
 -        void computeReferences(t_pbc *pbc);
 +        void computeReferences(t_pbc *pbc)
 +        {
 +            computeReferencesInternal(pbc, false);
 +        }
 +        void computeReferencesXY(t_pbc *pbc)
 +        {
 +            computeReferencesInternal(pbc, true);
 +        }
 +
 +        bool containsPair(int testIndex, const RefPair &pair) const
 +        {
 +            const std::vector<RefPair>          &refPairs = testPositions_[testIndex].refPairs;
 +            std::vector<RefPair>::const_iterator foundRefPair
 +                = std::lower_bound(refPairs.begin(), refPairs.end(), pair);
 +            if (foundRefPair == refPairs.end() || foundRefPair->refIndex != pair.refIndex)
 +            {
 +                return false;
 +            }
 +            return true;
 +        }
  
          gmx_rng_t                        rng_;
          real                             cutoff_;
          TestPositionList                 testPositions_;
  
      private:
 +        void computeReferencesInternal(t_pbc *pbc, bool bXY);
 +
          mutable rvec                    *testPos_;
  };
  
 +//! Shorthand for a collection of reference pairs.
 +typedef std::vector<NeighborhoodSearchTestData::RefPair> RefPairList;
 +
  NeighborhoodSearchTestData::NeighborhoodSearchTestData(int seed, real cutoff)
      : rng_(NULL), cutoff_(cutoff), refPosCount_(0), refPos_(NULL), testPos_(NULL)
  {
@@@ -243,7 -187,7 +239,7 @@@ void NeighborhoodSearchTestData::genera
      }
  }
  
 -void NeighborhoodSearchTestData::computeReferences(t_pbc *pbc)
 +void NeighborhoodSearchTestData::computeReferencesInternal(t_pbc *pbc, bool bXY)
  {
      real cutoff = cutoff_;
      if (cutoff <= 0)
              {
                  rvec_sub(i->x, refPos_[j], dx);
              }
 -            const real dist = norm(dx);
 +            // TODO: This may not work intuitively for 2D with the third box
 +            // vector not parallel to the Z axis, but neither does the actual
 +            // neighborhood search.
 +            const real dist =
 +                !bXY ? norm(dx) : sqrt(sqr(dx[XX]) + sqr(dx[YY]));
              if (dist < i->refMinDist)
              {
                  i->refMinDist      = dist;
              }
              if (dist <= cutoff)
              {
 -                i->refPairs.insert(j);
 +                RefPair pair(j, dist);
 +                GMX_RELEASE_ASSERT(i->refPairs.empty() || i->refPairs.back() < pair,
 +                                   "Reference pairs should be generated in sorted order");
 +                i->refPairs.push_back(pair);
              }
          }
      }
  }
  
 +/********************************************************************
 + * ExclusionsHelper
 + */
 +
 +class ExclusionsHelper
 +{
 +    public:
 +        static void markExcludedPairs(RefPairList *refPairs, int testIndex,
 +                                      const t_blocka *excls);
 +
 +        ExclusionsHelper(int refPosCount, int testPosCount);
 +
 +        void generateExclusions();
 +
 +        const t_blocka *exclusions() const { return &excls_; }
 +
 +        gmx::ConstArrayRef<int> refPosIds() const
 +        {
 +            return gmx::constArrayRefFromVector<int>(exclusionIds_.begin(),
 +                                                     exclusionIds_.begin() + refPosCount_);
 +        }
 +        gmx::ConstArrayRef<int> testPosIds() const
 +        {
 +            return gmx::constArrayRefFromVector<int>(exclusionIds_.begin(),
 +                                                     exclusionIds_.begin() + testPosCount_);
 +        }
 +
 +    private:
 +        int              refPosCount_;
 +        int              testPosCount_;
 +        std::vector<int> exclusionIds_;
 +        std::vector<int> exclsIndex_;
 +        std::vector<int> exclsAtoms_;
 +        t_blocka         excls_;
 +};
 +
 +// static
 +void ExclusionsHelper::markExcludedPairs(RefPairList *refPairs, int testIndex,
 +                                         const t_blocka *excls)
 +{
 +    int count = 0;
 +    for (int i = excls->index[testIndex]; i < excls->index[testIndex + 1]; ++i)
 +    {
 +        const int                           excludedIndex = excls->a[i];
 +        NeighborhoodSearchTestData::RefPair searchPair(excludedIndex, 0.0);
 +        RefPairList::iterator               excludedRefPair
 +            = std::lower_bound(refPairs->begin(), refPairs->end(), searchPair);
 +        if (excludedRefPair != refPairs->end()
 +            && excludedRefPair->refIndex == excludedIndex)
 +        {
 +            excludedRefPair->bFound    = true;
 +            excludedRefPair->bExcluded = true;
 +            ++count;
 +        }
 +    }
 +}
 +
 +ExclusionsHelper::ExclusionsHelper(int refPosCount, int testPosCount)
 +    : refPosCount_(refPosCount), testPosCount_(testPosCount)
 +{
 +    // Generate an array of 0, 1, 2, ...
 +    // TODO: Make the tests work also with non-trivial exclusion IDs,
 +    // and test that.
 +    exclusionIds_.resize(std::max(refPosCount, testPosCount), 1);
 +    exclusionIds_[0] = 0;
 +    std::partial_sum(exclusionIds_.begin(), exclusionIds_.end(),
 +                     exclusionIds_.begin());
 +
 +    excls_.nr           = 0;
 +    excls_.index        = NULL;
 +    excls_.nra          = 0;
 +    excls_.a            = NULL;
 +    excls_.nalloc_index = 0;
 +    excls_.nalloc_a     = 0;
 +}
 +
 +void ExclusionsHelper::generateExclusions()
 +{
 +    // TODO: Consider a better set of test data, where the density of the
 +    // particles would be higher, or where the exclusions would not be random,
 +    // to make a higher percentage of the exclusions to actually be within the
 +    // cutoff.
 +    exclsIndex_.reserve(testPosCount_ + 1);
 +    exclsAtoms_.reserve(testPosCount_ * 20);
 +    exclsIndex_.push_back(0);
 +    for (int i = 0; i < testPosCount_; ++i)
 +    {
 +        for (int j = 0; j < 20; ++j)
 +        {
 +            exclsAtoms_.push_back(i + j*3);
 +        }
 +        exclsIndex_.push_back(exclsAtoms_.size());
 +    }
 +    excls_.nr    = exclsIndex_.size();
 +    excls_.index = &exclsIndex_[0];
 +    excls_.nra   = exclsAtoms_.size();
 +    excls_.a     = &exclsAtoms_[0];
 +}
 +
  /********************************************************************
   * NeighborhoodSearchTest
   */
@@@ -402,10 -240,6 +398,10 @@@ class NeighborhoodSearchTest : public :
                                const NeighborhoodSearchTestData &data);
          void testPairSearch(gmx::AnalysisNeighborhoodSearch  *search,
                              const NeighborhoodSearchTestData &data);
 +        void testPairSearchFull(gmx::AnalysisNeighborhoodSearch          *search,
 +                                const NeighborhoodSearchTestData         &data,
 +                                const gmx::AnalysisNeighborhoodPositions &pos,
 +                                const t_blocka                           *excls);
  
          gmx::AnalysisNeighborhood        nb_;
  };
@@@ -448,8 -282,6 +444,8 @@@ void NeighborhoodSearchTest::testNeares
          {
              EXPECT_EQ(i->refNearestPoint, pair.refIndex());
              EXPECT_EQ(0, pair.testIndex());
 +            EXPECT_REAL_EQ_TOL(i->refMinDist, sqrt(pair.distance2()),
 +                               gmx::test::ulpTolerance(64));
          }
          else
          {
      }
  }
  
 +/*! \brief
 + * Helper function to check that all expected pairs were found.
 + */
 +static void checkAllPairsFound(const RefPairList &refPairs)
 +{
 +    // This could be elegantly expressed with Google Mock matchers, but that
 +    // has a significant effect on the runtime of the tests...
 +    for (RefPairList::const_iterator i = refPairs.begin(); i != refPairs.end(); ++i)
 +    {
 +        if (!i->bFound)
 +        {
 +            ADD_FAILURE()
 +            << "Some pairs within the cutoff were not found.";
 +            break;
 +        }
 +    }
 +}
 +
  void NeighborhoodSearchTest::testPairSearch(
          gmx::AnalysisNeighborhoodSearch  *search,
          const NeighborhoodSearchTestData &data)
  {
 -    NeighborhoodSearchTestData::TestPositionList::const_iterator i;
 -    for (i = data.testPositions_.begin(); i != data.testPositions_.end(); ++i)
 +    testPairSearchFull(search, data, data.testPositions(), NULL);
 +}
 +
 +void NeighborhoodSearchTest::testPairSearchFull(
 +        gmx::AnalysisNeighborhoodSearch          *search,
 +        const NeighborhoodSearchTestData         &data,
 +        const gmx::AnalysisNeighborhoodPositions &pos,
 +        const t_blocka                           *excls)
 +{
 +    // TODO: Some parts of this code do not work properly if pos does not
 +    // contain all the test positions.
 +    std::set<int> remainingTestPositions;
 +    for (size_t i = 0; i < data.testPositions_.size(); ++i)
      {
 -        std::set<int> checkSet                         = i->refPairs;
 -        gmx::AnalysisNeighborhoodPairSearch pairSearch =
 -            search->startPairSearch(i->x);
 -        gmx::AnalysisNeighborhoodPair       pair;
 -        while (pairSearch.findNextPair(&pair))
 +        remainingTestPositions.insert(i);
 +    }
 +    gmx::AnalysisNeighborhoodPairSearch pairSearch
 +        = search->startPairSearch(pos);
 +    gmx::AnalysisNeighborhoodPair       pair;
 +    // TODO: There is an ordering assumption here that may break in the future:
 +    // all pairs for a test position are assumed to be returned consencutively.
 +    RefPairList refPairs;
 +    int         prevTestPos = -1;
 +    while (pairSearch.findNextPair(&pair))
 +    {
 +        if (pair.testIndex() != prevTestPos)
          {
 -            EXPECT_EQ(0, pair.testIndex());
 -            if (checkSet.erase(pair.refIndex()) == 0)
 +            if (prevTestPos != -1)
 +            {
 +                checkAllPairsFound(refPairs);
 +            }
 +            const int testIndex = pair.testIndex();
 +            if (remainingTestPositions.count(testIndex) == 0)
              {
 -                // TODO: Check whether the same pair was returned more than
 -                // once and give a better error message if so.
                  ADD_FAILURE()
 -                << "Expected: Position " << pair.refIndex()
 -                << " is within cutoff.\n"
 -                << "  Actual: It is not.";
 +                << "Pairs for test position " << testIndex
 +                << " are returned more than once.";
 +            }
 +            remainingTestPositions.erase(testIndex);
 +            refPairs = data.testPositions_[testIndex].refPairs;
 +            if (excls != NULL)
 +            {
 +                ExclusionsHelper::markExcludedPairs(&refPairs, testIndex, excls);
              }
 +            prevTestPos = testIndex;
 +        }
 +
 +        NeighborhoodSearchTestData::RefPair searchPair(pair.refIndex(),
 +                                                       sqrt(pair.distance2()));
 +        RefPairList::iterator               foundRefPair
 +            = std::lower_bound(refPairs.begin(), refPairs.end(), searchPair);
 +        if (foundRefPair == refPairs.end() || foundRefPair->refIndex != pair.refIndex())
 +        {
 +            ADD_FAILURE()
 +            << "Expected: Pair (ref: " << pair.refIndex() << ", test: "
 +            << pair.testIndex() << ") is not within the cutoff.\n"
 +            << "  Actual: It is returned.";
 +        }
 +        else if (foundRefPair->bExcluded)
 +        {
 +            ADD_FAILURE()
 +            << "Expected: Pair (ref: " << pair.refIndex() << ", test: "
 +            << pair.testIndex() << ") is excluded from the search.\n"
 +            << "  Actual: It is returned.";
 +        }
 +        else if (foundRefPair->bFound)
 +        {
 +            ADD_FAILURE()
 +            << "Expected: Pair (ref: " << pair.refIndex() << ", test: "
 +            << pair.testIndex() << ") is returned only once.\n"
 +            << "  Actual: It is returned multiple times.";
 +        }
 +        else
 +        {
 +            foundRefPair->bFound = true;
 +            EXPECT_REAL_EQ_TOL(foundRefPair->distance, searchPair.distance,
 +                               gmx::test::ulpTolerance(64))
 +            << "Distance computed by the neighborhood search does not match.";
 +        }
 +    }
 +    checkAllPairsFound(refPairs);
 +    for (std::set<int>::const_iterator i = remainingTestPositions.begin();
 +         i != remainingTestPositions.end(); ++i)
 +    {
 +        if (!data.testPositions_[*i].refPairs.empty())
 +        {
 +            ADD_FAILURE()
 +            << "Expected: Pairs would be returned for test position " << *i << ".\n"
 +            << "  Actual: None were returned.";
 +            break;
          }
 -        EXPECT_TRUE(checkSet.empty()) << "Some positions were not returned by the pair search.";
      }
  }
  
@@@ -628,32 -372,6 +624,32 @@@ class RandomBoxFullPBCDat
          NeighborhoodSearchTestData data_;
  };
  
 +class RandomBoxXYFullPBCData
 +{
 +    public:
 +        static const NeighborhoodSearchTestData &get()
 +        {
 +            static RandomBoxXYFullPBCData singleton;
 +            return singleton.data_;
 +        }
 +
 +        RandomBoxXYFullPBCData() : data_(54321, 1.0)
 +        {
 +            data_.box_[XX][XX] = 10.0;
 +            data_.box_[YY][YY] = 5.0;
 +            data_.box_[ZZ][ZZ] = 7.0;
 +            // TODO: Consider whether manually picking some positions would give better
 +            // test coverage.
 +            data_.generateRandomRefPositions(1000);
 +            data_.generateRandomTestPositions(100);
 +            set_pbc(&data_.pbc_, epbcXYZ, data_.box_);
 +            data_.computeReferencesXY(&data_.pbc_);
 +        }
 +
 +    private:
 +        NeighborhoodSearchTestData data_;
 +};
 +
  class RandomTriclinicFullPBCData
  {
      public:
@@@ -775,24 -493,6 +771,24 @@@ TEST_F(NeighborhoodSearchTest, GridSear
      testPairSearch(&search, data);
  }
  
 +TEST_F(NeighborhoodSearchTest, GridSearchXYBox)
 +{
 +    const NeighborhoodSearchTestData &data = RandomBoxXYFullPBCData::get();
 +
 +    nb_.setCutoff(data.cutoff_);
 +    nb_.setMode(gmx::AnalysisNeighborhood::eSearchMode_Grid);
 +    nb_.setXYMode(true);
 +    gmx::AnalysisNeighborhoodSearch search =
 +        nb_.initSearch(&data.pbc_, data.refPositions());
 +    // Currently, grid searching not supported with XY.
 +    //ASSERT_EQ(gmx::AnalysisNeighborhood::eSearchMode_Grid, search.mode());
 +
 +    testIsWithin(&search, data);
 +    testMinimumDistance(&search, data);
 +    testNearestPoint(&search, data);
 +    testPairSearch(&search, data);
 +}
 +
  TEST_F(NeighborhoodSearchTest, HandlesConcurrentSearches)
  {
      const NeighborhoodSearchTestData &data = TrivialTestData::get();
      testPairSearch(&search2, data);
  
      gmx::AnalysisNeighborhoodPair pair;
 -    pairSearch1.findNextPair(&pair);
 +    ASSERT_TRUE(pairSearch1.findNextPair(&pair))
 +    << "Test data did not contain any pairs for position 0 (problem in the test).";
      EXPECT_EQ(0, pair.testIndex());
 -    EXPECT_TRUE(data.testPositions_[0].refPairs.count(pair.refIndex()) == 1);
 +    {
 +        NeighborhoodSearchTestData::RefPair searchPair(pair.refIndex(), sqrt(pair.distance2()));
 +        EXPECT_TRUE(data.containsPair(0, searchPair));
 +    }
  
 -    pairSearch2.findNextPair(&pair);
 +    ASSERT_TRUE(pairSearch2.findNextPair(&pair))
 +    << "Test data did not contain any pairs for position 1 (problem in the test).";
      EXPECT_EQ(1, pair.testIndex());
 -    EXPECT_TRUE(data.testPositions_[1].refPairs.count(pair.refIndex()) == 1);
 +    {
 +        NeighborhoodSearchTestData::RefPair searchPair(pair.refIndex(), sqrt(pair.distance2()));
 +        EXPECT_TRUE(data.containsPair(1, searchPair));
 +    }
  }
  
  TEST_F(NeighborhoodSearchTest, HandlesSkippingPairs)
              ++currentIndex;
          }
          EXPECT_EQ(currentIndex, pair.testIndex());
 -        EXPECT_TRUE(data.testPositions_[currentIndex].refPairs.count(pair.refIndex()) == 1);
 +        NeighborhoodSearchTestData::RefPair searchPair(pair.refIndex(), sqrt(pair.distance2()));
 +        EXPECT_TRUE(data.containsPair(currentIndex, searchPair));
          pairSearch.skipRemainingPairsForTestPosition();
          ++currentIndex;
      }
  }
  
 +TEST_F(NeighborhoodSearchTest, SimpleSearchExclusions)
 +{
 +    const NeighborhoodSearchTestData &data = RandomBoxFullPBCData::get();
 +
 +    ExclusionsHelper                  helper(data.refPosCount_, data.testPositions_.size());
 +    helper.generateExclusions();
 +
 +    nb_.setCutoff(data.cutoff_);
 +    nb_.setTopologyExclusions(helper.exclusions());
 +    nb_.setMode(gmx::AnalysisNeighborhood::eSearchMode_Simple);
 +    gmx::AnalysisNeighborhoodSearch search =
 +        nb_.initSearch(&data.pbc_,
 +                       data.refPositions().exclusionIds(helper.refPosIds()));
 +    ASSERT_EQ(gmx::AnalysisNeighborhood::eSearchMode_Simple, search.mode());
 +
 +    testPairSearchFull(&search, data,
 +                       data.testPositions().exclusionIds(helper.testPosIds()),
 +                       helper.exclusions());
 +}
 +
 +TEST_F(NeighborhoodSearchTest, GridSearchExclusions)
 +{
 +    const NeighborhoodSearchTestData &data = RandomBoxFullPBCData::get();
 +
 +    ExclusionsHelper                  helper(data.refPosCount_, data.testPositions_.size());
 +    helper.generateExclusions();
 +
 +    nb_.setCutoff(data.cutoff_);
 +    nb_.setTopologyExclusions(helper.exclusions());
 +    nb_.setMode(gmx::AnalysisNeighborhood::eSearchMode_Grid);
 +    gmx::AnalysisNeighborhoodSearch search =
 +        nb_.initSearch(&data.pbc_,
 +                       data.refPositions().exclusionIds(helper.refPosIds()));
 +    ASSERT_EQ(gmx::AnalysisNeighborhood::eSearchMode_Grid, search.mode());
 +
 +    testPairSearchFull(&search, data,
 +                       data.testPositions().exclusionIds(helper.testPosIds()),
 +                       helper.exclusions());
 +}
 +
  } // namespace
index 89db4cd4eb2cc9ded578f5efdb33895b2a74c559,70784dbc78e7cc7b46527375ae33aaef6cc43484..3e6555c967c3c695108eac8a11930c0c1f091132
@@@ -32,9 -32,9 +32,9 @@@
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
 +
 +#include "config.h"
  
  #include <vector>
  #include "gromacs/math/utilities.h"
@@@ -60,7 -60,7 +60,7 @@@ class Simd4MathTest : public Simd4Tes
      public:
          ::testing::AssertionResult
                               compareSimd4MathFunction(const char * refFuncExpr, const char *simd4FuncExpr,
-                                                       real refFunc(real x),     gmx_simd4_real_t simd4Func(gmx_simd4_real_t x));
+                                                       real refFunc(real x),     gmx_simd4_real_t gmx_simdcall simd4Func(gmx_simd4_real_t x));
  };
  
  /*! \brief Test approximate equality of SIMD4 vs reference version of a function.
@@@ -85,7 -85,7 +85,7 @@@
   */
  ::testing::AssertionResult
  Simd4MathTest::compareSimd4MathFunction(const char * refFuncExpr, const char *simd4FuncExpr,
-                                         real refFunc(real x),     gmx_simd4_real_t simd4Func(gmx_simd4_real_t x))
+                                         real refFunc(real x),     gmx_simd4_real_t gmx_simdcall simd4Func(gmx_simd4_real_t x))
  {
      std::vector<real>            vx(GMX_SIMD4_WIDTH);
      std::vector<real>            vref(GMX_SIMD4_WIDTH);
index 8a0d2029419c67045f715367835f995f62ba0f20,2fab43ca7edbfc8dbd51cc3865194eb822b20da1..6899a9ee00a8ced742097268d5c95222bcfaab6e
@@@ -32,9 -32,9 +32,9 @@@
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "gmxpre.h"
 +
 +#include "config.h"
  
  #include <vector>
  #include "gromacs/math/utilities.h"
@@@ -60,7 -60,7 +60,7 @@@ class SimdMathTest : public SimdTes
      public:
          ::testing::AssertionResult
                              compareSimdMathFunction(const char * refFuncExpr, const char *simdFuncExpr,
-                                                     real refFunc(real x),     gmx_simd_real_t simdFunc(gmx_simd_real_t x));
+                                                     real refFunc(real x),     gmx_simd_real_t gmx_simdcall simdFunc(gmx_simd_real_t x));
  };
  
  /*! \brief Test approximate equality of SIMD vs reference version of a function.
@@@ -84,7 -84,7 +84,7 @@@
   */
  ::testing::AssertionResult
  SimdMathTest::compareSimdMathFunction(const char * refFuncExpr, const char *simdFuncExpr,
-                                       real refFunc(real x),     gmx_simd_real_t simdFunc(gmx_simd_real_t x))
+                                       real refFunc(real x),     gmx_simd_real_t gmx_simdcall simdFunc(gmx_simd_real_t x))
  {
      std::vector<real>            vx(GMX_SIMD_REAL_WIDTH);
      std::vector<real>            vref(GMX_SIMD_REAL_WIDTH);
@@@ -208,7 -208,7 +208,7 @@@ TEST_F(SimdMathTest, gmxSimdInvsqrtR
  }
  
  /*! \brief Function wrapper to return first result when testing \ref gmx_simd_invsqrt_pair_r */
- gmx_simd_real_t
+ gmx_simd_real_t gmx_simdcall
  tst_invsqrt_pair0(gmx_simd_real_t x)
  {
      gmx_simd_real_t r0, r1;
  }
  
  /*! \brief Function wrapper to return second result when testing \ref gmx_simd_invsqrt_pair_r */
- gmx_simd_real_t
+ gmx_simd_real_t gmx_simdcall
  tst_invsqrt_pair1(gmx_simd_real_t x)
  {
      gmx_simd_real_t r0, r1;
index 0737f413aa901b87196c3bada305d6fbf4002271,7751db43906c65805b076820fd707be7f2d0dad9..fcacc5e2042bfc42d1fccfaf2d19b7f99ad3b3cc
@@@ -49,7 -49,9 +49,7 @@@
   * define HAVE_RDTSCP to use the serializing rdtscp instruction instead of rdtsc.
   * This is only supported on newer Intel/AMD hardware, but provides better accuracy.
   */
 -#ifdef HAVE_CONFIG_H
  #include "config.h"
 -#endif
  
  #ifdef _MSC_VER
  #include <intrin.h>
@@@ -77,6 -79,11 +77,11 @@@ extern "C
  typedef unsigned long long
      gmx_cycles_t;
  
+ #elif ((defined __aarch64__) && (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__PATHSCALE__) || defined(__PGIC__)))
+ /* 64-bit ARM cycle counters with GCC inline assembly */
+ typedef unsigned long long
+     gmx_cycles_t;
  #elif defined(_MSC_VER)
  #include <windows.h>
  typedef __int64
@@@ -208,6 -215,12 +213,12 @@@ static __inline__ int gmx_cycles_have_c
      /* x86 or x86-64 with GCC inline assembly - pentium TSC register */
      return 1;
  }
+ #elif ((defined __aarch64__) && (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__PATHSCALE__) || defined(__PGIC__)))
+ static __inline int gmx_cycles_have_counter(void)
+ {
+     /* 64-bit ARM cycle counters with GCC inline assembly */
+     return 1;
+ }
  #elif (defined(_MSC_VER))
  static __inline int gmx_cycles_have_counter(void)
  {
@@@ -348,14 -361,30 +359,30 @@@ static __inline__ gmx_cycles_t gmx_cycl
  
      return cycle;
  }
+ #elif ((defined __aarch64__) && (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__PATHSCALE__) || defined(__PGIC__)))
+ static __inline__ gmx_cycles_t gmx_cycles_read(void)
+ {
+     /* 64-bit ARM cycle counters with GCC inline assembly */
+     gmx_cycles_t   cycle;
+     __asm__ __volatile__("mrs %0, cntvct_el0" : "=r" (cycle) );
+     return cycle;
+ }
  #elif defined(_MSC_VER)
  static __inline gmx_cycles_t gmx_cycles_read(void)
  {
- #ifdef HAVE_RDTSCP
+ #ifdef _M_ARM
+     /* Windows on 64-bit ARM */
+     return __rdpmccntr64();
+ #else
+     /* x86 */
+ #    ifdef HAVE_RDTSCP
      unsigned int ui;
      return __rdtscp(&ui);
- #else
+ #    else
      return __rdtsc();
+ #    endif
  #endif
  }
  #elif (defined(__hpux) || defined(__HP_cc)) && defined(__ia64)
index e353096686b8d742e68ab52226ff37652e631fab,98c31b55b1777642edf9becbe258067cbc487017..cedfaa6c83ca009c3207e13ce36def1e82d51c69
   * 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 "gromacs/timing/wallcycle.h"
  
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 +#include "config.h"
  
 +#include <stdlib.h>
  #include <string.h>
  
 -#include "gromacs/utility/smalloc.h"
 -#include "gmx_fatal.h"
 -#include "md_logging.h"
 +#include "gromacs/legacyheaders/md_logging.h"
 +#include "gromacs/legacyheaders/types/commrec.h"
  #include "gromacs/utility/cstringutil.h"
 -
 -#include "gromacs/timing/cyclecounter.h"
 +#include "gromacs/utility/fatalerror.h"
  #include "gromacs/utility/gmxmpi.h"
 +#include "gromacs/utility/smalloc.h"
 +
 +#include "cyclecounter.h"
  
  /* DEBUG_WCYCLE adds consistency checking for the counters.
   * It checks if you stop a counter different from the last
@@@ -101,7 -99,8 +101,8 @@@ static const char *wcn[ewcNR] 
      "Comm. coord.", "Born radii", "Force", "Wait + Comm. F", "PME mesh",
      "PME redist. X/F", "PME spread/gather", "PME 3D-FFT", "PME 3D-FFT Comm.", "PME solve LJ", "PME solve Elec",
      "PME wait for PP", "Wait + Recv. PME F", "Wait GPU nonlocal", "Wait GPU local", "NB X/F buffer ops.",
-     "Vsite spread", "Write traj.", "Update", "Constraints", "Comm. energies",
+     "Vsite spread", "COM pull force",
+     "Write traj.", "Update", "Constraints", "Comm. energies",
      "Enforced rotation", "Add rot. forces", "Coordinate swapping", "IMD", "Test"
  };
  
index 8cb131f8398a5326ff285c22ddca4c4d0eaf5b81,f91a455fb53bd395801341770208c803ff569c54..70b0341081876fd49ac1ef5ca8c3e0434601e096
  #define GMX_TIMING_WALLCYCLE_H
  
  #include <stdio.h>
 -#include "gromacs/legacyheaders/typedefs.h"
 -#include "gromacs/legacyheaders/types/commrec.h"
 +
 +#include "../legacyheaders/types/commrec_fwd.h"
 +#include "../legacyheaders/types/nbnxn_cuda_types_ext.h"
 +#include "../utility/basedefinitions.h"
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
 +typedef struct gmx_wallcycle *gmx_wallcycle_t;
 +
  enum {
      ewcRUN, ewcSTEP, ewcPPDURINGPME, ewcDOMDEC, ewcDDCOMMLOAD,
      ewcDDCOMMBOUND, ewcVSITECONSTR, ewcPP_PMESENDX, ewcNS, ewcLAUNCH_GPU_NB,
      ewcMOVEX, ewcGB, ewcFORCE, ewcMOVEF, ewcPMEMESH,
      ewcPME_REDISTXF, ewcPME_SPREADGATHER, ewcPME_FFT, ewcPME_FFTCOMM, ewcLJPME, ewcPME_SOLVE,
      ewcPMEWAITCOMM, ewcPP_PMEWAITRECVF, ewcWAIT_GPU_NB_NL, ewcWAIT_GPU_NB_L, ewcNB_XF_BUF_OPS,
-     ewcVSITESPREAD, ewcTRAJ, ewcUPDATE, ewcCONSTR, ewcMoveE, ewcROT, ewcROTadd, ewcSWAP, ewcIMD,
+     ewcVSITESPREAD, ewcPULLPOT,
+     ewcTRAJ, ewcUPDATE, ewcCONSTR, ewcMoveE, ewcROT, ewcROTadd, ewcSWAP, ewcIMD,
      ewcTEST, ewcNR
  };
  
index 18a898cce5f6e919bd5e33c5f47437806db30038,0000000000000000000000000000000000000000..faa4395328c4c3eaefabbf99dc4b2a2bf2e60ac2
mode 100644,000000..100644
--- /dev/null
@@@ -1,207 -1,0 +1,210 @@@
 +/*
 + * 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
 + * Basic types and macros used throughout \Gromacs.
 + *
 + * \inpublicapi
 + * \ingroup module_utility
 + */
 +#ifndef GMX_UTILITY_BASEDEFINITIONS_H
 +#define GMX_UTILITY_BASEDEFINITIONS_H
 +
 +/* Information about integer data type sizes */
 +#include <limits.h>
 +#define __STDC_LIMIT_MACROS
 +#include <stdint.h>
 +#ifndef _MSC_VER
 +#define __STDC_FORMAT_MACROS
 +#include <inttypes.h>
 +#endif
 +
 +/*! \brief
 + * Boolean type for use in \Gromacs C code.
 + *
 + * There is no standard size for 'bool' in C++, so when
 + * we previously defined it to int for C code the data types
 + * (and structs) would have different size depending on your compiler,
 + * both at \Gromacs build time and when you use the library.
 + * The only way around this is to NOT assume anything about the C++ type,
 + * so we cannot use the name 'bool' in our C code anymore.
 + */
 +typedef int gmx_bool;
 +
 +#ifndef FALSE
 +/** False value for ::gmx_bool. */
 +#  define FALSE   0
 +#endif
 +#ifndef TRUE
 +/** True value for ::gmx_bool. */
 +#  define TRUE    1
 +#endif
 +/** Number of gmx_bool values. */
 +#define BOOL_NR 2
 +
 +/*! \name Fixed-width integer types
 + *
 + * These types and macros provide the equivalent of 32- and 64-bit integer
 + * types from C99 headers `stdint.h` and `inttypes.h`.  These headers are also
 + * there in C++11.  The types and macros from here should be used instead of
 + * `int32_t` etc.
 + * MSVC doesn't support these before Visual Studio 2013.
 + */
 +/*! \{ */
 +#ifdef _MSC_VER
 +typedef __int32 gmx_int32_t;
 +#define GMX_PRId32 "I32d"
 +#define GMX_SCNd32 "I32d"
 +
 +typedef __int64 gmx_int64_t;
 +#define GMX_PRId64 "I64d"
 +#define GMX_SCNd64 "I64d"
 +
 +typedef unsigned __int32 gmx_uint32_t;
 +#define GMX_PRIu32 "I32u"
 +#define GMX_SCNu32 "I32u"
 +
 +typedef unsigned __int64 gmx_uint64_t;
 +#define GMX_PRIu64 "I64u"
 +#define GMX_SCNu64 "I64u"
 +#else
 +typedef int32_t gmx_int32_t;
 +#define GMX_PRId32 PRId32
 +#define GMX_SCNd32 SCNd32
 +
 +typedef int64_t gmx_int64_t;
 +#define GMX_PRId64 PRId64
 +#define GMX_SCNd64 SCNd64
 +
 +typedef uint32_t gmx_uint32_t;
 +#define GMX_PRIu32 PRIu32
 +#define GMX_SCNu32 SCNu32
 +
 +typedef uint64_t gmx_uint64_t;
 +#define GMX_PRIu64 PRIu64
 +#define GMX_SCNu64 SCNu64
 +#endif
 +
 +#define GMX_INT32_MAX INT32_MAX
 +#define GMX_INT32_MIN INT32_MIN
 +
 +#define GMX_INT64_MAX INT64_MAX
 +#define GMX_INT64_MIN INT64_MIN
 +
 +#define GMX_UINT32_MAX UINT32_MAX
 +#define GMX_UINT32_MIN UINT32_MIN
 +
 +#define GMX_UINT64_MAX UINT64_MAX
 +#define GMX_UINT64_MIN UINT64_MIN
 +/*! \} */
 +
 +/*! \def gmx_inline
 + * \brief
 + * Keyword to use in C code instead of C99 `inline`.
 + *
 + * Some of the C compilers we support do not recognize the C99 keyword
 + * `inline`.  This macro should be used in C code and in shared C/C++ headers
 + * to indicate a function is inlined.
 + * C++ code should use plain `inline`, as that is already in C++98.
 + */
 +#if !defined __cplusplus && _MSC_VER
 +#define gmx_inline __inline
 +#else
 +/* C++ or C99 */
 +#define gmx_inline inline
 +#endif
 +
 +/* ICC, GCC, MSVC, Pathscale, PGI, XLC support __restrict.
 + * Any other compiler can be added here. */
 +/*! \brief
 + * Keyword to use in instead of C99 `restrict`.
 + *
 + * We cannot use `restrict` because it is only in C99, but not in C++.
 + * This macro should instead be used to allow easily supporting different
 + * compilers.
 + */
 +#define gmx_restrict __restrict
 +
 +/*! \def gmx_cxx_const
 + * \brief
 + * Keyword to work around C/C++ differences in possible const keyword usage.
 + *
 + * Some functions that do not modify their input parameters cannot declare
 + * those parameters as `const` and compile warning/error-free on both C and C++
 + * compilers because of differences in `const` semantics.  This macro can be
 + * used in cases where C++ allows `const`, but C does not like it, to make the
 + * same declaration work for both.
 + */
 +#ifdef __cplusplus
 +#define gmx_cxx_const const
 +#else
 +#define gmx_cxx_const
 +#endif
 +
 +/*! \def gmx_unused
 + * \brief
 + * Attribute to suppress compiler warnings about unused function parameters.
 + *
 + * This attribute suppresses compiler warnings about unused function arguments
 + * by marking them as possibly unused.  Some arguments are unused but
 + * have to be retained to preserve a function signature
 + * that must match that of another function.
 + * Some arguments are only used in *some* conditional compilation code paths
 + * (e.g. MPI).
 + */
 +#ifndef gmx_unused
 +#ifdef __GNUC__
 +/* GCC, clang, and some ICC pretending to be GCC */
 +#  define gmx_unused __attribute__ ((unused))
 +#elif (defined(__INTEL_COMPILER) || defined(__ECC)) && !defined(_MSC_VER)
 +/* ICC on *nix */
 +#  define gmx_unused __attribute__ ((unused))
++#elif defined(__PGI)
++/* Portland group compilers */
++#  define gmx_unused __attribute__ ((unused))
 +#elif defined _MSC_VER
 +/* MSVC */
 +#  define gmx_unused /*@unused@*/
 +#elif defined(__xlC__)
 +/* IBM */
 +#  define gmx_unused __attribute__ ((unused))
 +#else
 +#  define gmx_unused
 +#endif
 +#endif
 +
 +#endif
index 3bf621fe6dab644c5900421e39a218ca15fa99c7,2b320246b588bfd34c87f02885847096fa53499f..259484cc18018aca3a2c67394350281c6a0391ed
   * To help us fund GROMACS development, we humbly ask that you cite
   * the research papers on the package. Check out http://www.gromacs.org.
   */
 -#ifdef HAVE_CONFIG_H
 -#include <config.h>
 -#endif
 -
 -#include "typedefs.h"
 -#include "gromacs/utility/smalloc.h"
 -#include "sysstuff.h"
 -#include "vec.h"
 -#include "vcm.h"
 -#include "mdebin.h"
 -#include "nrnb.h"
 -#include "calcmu.h"
 -#include "index.h"
 -#include "vsite.h"
 -#include "update.h"
 -#include "ns.h"
 -#include "mdrun.h"
 -#include "md_support.h"
 -#include "md_logging.h"
 -#include "network.h"
 -#include "xvgr.h"
 -#include "physics.h"
 -#include "names.h"
 -#include "force.h"
 -#include "disre.h"
 -#include "orires.h"
 -#include "pme.h"
 -#include "mdatoms.h"
 +#include "gmxpre.h"
 +
 +#include "config.h"
 +
 +#include <stdlib.h>
 +
 +#include "gromacs/legacyheaders/typedefs.h"
 +#include "gromacs/math/vec.h"
 +#include "gromacs/legacyheaders/vcm.h"
 +#include "gromacs/legacyheaders/mdebin.h"
 +#include "gromacs/legacyheaders/nrnb.h"
 +#include "gromacs/legacyheaders/calcmu.h"
 +#include "gromacs/legacyheaders/vsite.h"
 +#include "gromacs/legacyheaders/update.h"
 +#include "gromacs/legacyheaders/ns.h"
 +#include "gromacs/legacyheaders/mdrun.h"
 +#include "gromacs/legacyheaders/md_support.h"
 +#include "gromacs/legacyheaders/md_logging.h"
 +#include "gromacs/legacyheaders/network.h"
 +#include "gromacs/legacyheaders/names.h"
 +#include "gromacs/legacyheaders/force.h"
 +#include "gromacs/legacyheaders/disre.h"
 +#include "gromacs/legacyheaders/orires.h"
 +#include "gromacs/legacyheaders/pme.h"
 +#include "gromacs/legacyheaders/mdatoms.h"
  #include "repl_ex.h"
  #include "deform.h"
 -#include "qmmm.h"
 -#include "domdec.h"
 -#include "domdec_network.h"
 -#include "gromacs/gmxlib/topsort.h"
 -#include "coulomb.h"
 -#include "constr.h"
 -#include "shellfc.h"
 +#include "gromacs/legacyheaders/qmmm.h"
 +#include "gromacs/legacyheaders/domdec.h"
 +#include "gromacs/legacyheaders/domdec_network.h"
 +#include "gromacs/legacyheaders/coulomb.h"
 +#include "gromacs/legacyheaders/constr.h"
 +#include "gromacs/legacyheaders/shellfc.h"
  #include "gromacs/gmxpreprocess/compute_io.h"
 -#include "checkpoint.h"
 -#include "mtop_util.h"
 -#include "sighandler.h"
 -#include "txtdump.h"
 +#include "gromacs/legacyheaders/checkpoint.h"
 +#include "gromacs/topology/mtop_util.h"
 +#include "gromacs/legacyheaders/sighandler.h"
 +#include "gromacs/legacyheaders/txtdump.h"
  #include "gromacs/utility/cstringutil.h"
  #include "pme_loadbal.h"
 -#include "bondf.h"
 +#include "gromacs/legacyheaders/bondf.h"
  #include "membed.h"
 -#include "types/nlistheuristics.h"
 -#include "types/iteratedconstraints.h"
 -#include "nbnxn_cuda_data_mgmt.h"
 +#include "gromacs/legacyheaders/types/nlistheuristics.h"
 +#include "gromacs/legacyheaders/types/iteratedconstraints.h"
 +#include "gromacs/mdlib/nbnxn_cuda/nbnxn_cuda_data_mgmt.h"
  
 -#include "gromacs/utility/gmxmpi.h"
  #include "gromacs/fileio/confio.h"
 +#include "gromacs/fileio/mdoutf.h"
  #include "gromacs/fileio/trajectory_writing.h"
  #include "gromacs/fileio/trnio.h"
  #include "gromacs/fileio/trxio.h"
  #include "gromacs/fileio/xtcio.h"
 -#include "gromacs/timing/wallcycle.h"
 -#include "gromacs/timing/walltime_accounting.h"
 +#include "gromacs/imd/imd.h"
 +#include "gromacs/pbcutil/mshift.h"
 +#include "gromacs/pbcutil/pbc.h"
  #include "gromacs/pulling/pull.h"
  #include "gromacs/swap/swapcoords.h"
 -#include "gromacs/imd/imd.h"
 +#include "gromacs/timing/wallcycle.h"
 +#include "gromacs/timing/walltime_accounting.h"
 +#include "gromacs/utility/gmxmpi.h"
 +#include "gromacs/utility/smalloc.h"
  
  #ifdef GMX_FAHCORE
  #include "corewrap.h"
@@@ -105,7 -105,7 +105,7 @@@ static void reset_all_counters(FILE *fp
                                 gmx_int64_t *step_rel, t_inputrec *ir,
                                 gmx_wallcycle_t wcycle, t_nrnb *nrnb,
                                 gmx_walltime_accounting_t walltime_accounting,
 -                               nbnxn_cuda_ptr_t cu_nbv)
 +                               struct nonbonded_verlet_t *nbv)
  {
      char sbuf[STEPSTRSIZE];
  
      md_print_warn(cr, fplog, "step %s: resetting all time and cycle counters\n",
                    gmx_step_str(step, sbuf));
  
 -    if (cu_nbv)
 -    {
 -        nbnxn_cuda_reset_timings(cu_nbv);
 -    }
 +    nbnxn_cuda_reset_timings(nbv);
  
      wallcycle_stop(wcycle, ewcRUN);
      wallcycle_reset_all(wcycle);
@@@ -167,7 -170,7 +167,7 @@@ double do_md(FILE *fplog, t_commrec *cr
      rvec              mu_tot;
      t_vcm            *vcm;
      t_state          *bufstate = NULL;
 -    matrix           *scale_tot, pcoupl_mu, M, ebox;
 +    matrix            pcoupl_mu, M;
      gmx_nlheur_t      nlh;
      t_trxframe        rerun_fr;
      gmx_repl_ex_t     repl_ex = NULL;
      gmx_ekindata_t   *ekind, *ekind_save;
      gmx_shellfc_t     shellfc;
      int               count, nconverged = 0;
 -    real              timestep   = 0;
 -    double            tcount     = 0;
 -    gmx_bool          bConverged = TRUE, bOK, bSumEkinhOld, bDoReplEx, bExchanged, bNeedRepartition;
 -    gmx_bool          bAppend;
 +    double            tcount                 = 0;
 +    gmx_bool          bConverged             = TRUE, bSumEkinhOld, bDoReplEx, bExchanged, bNeedRepartition;
      gmx_bool          bResetCountersHalfMaxH = FALSE;
      gmx_bool          bVV, bIterativeCase, bFirstIterate, bTemp, bPres, bTrotter;
      gmx_bool          bUpdateDoLR;
      double            cycles;
      real              saved_conserved_quantity = 0;
      real              last_ekin                = 0;
 -    int               iter_i;
      t_extmass         MassQ;
      int             **trotter_seq;
      char              sbuf[STEPSTRSIZE], sbuf2[STEPSTRSIZE];
  
      /* Check for special mdrun options */
      bRerunMD = (Flags & MD_RERUN);
 -    bAppend  = (Flags & MD_APPENDFILES);
      if (Flags & MD_RESETCOUNTERSHALFWAY)
      {
          if (ir->nsteps > 0)
       */
      if ((Flags & MD_TUNEPME) &&
          EEL_PME(fr->eeltype) &&
 -        ( (fr->cutoff_scheme == ecutsVERLET && fr->nbv->bUseGPU) || !(cr->duty & DUTY_PME)) &&
 +        ( use_GPU(fr->nbv) || !(cr->duty & DUTY_PME)) &&
          !bRerunMD)
      {
          pme_loadbal_init(&pme_loadbal, ir, state->box, fr->ic, fr->pmedata);
      bStateFromTPX    = !bStateFromCP;
      bInitStep        = bFirstStep && (bStateFromTPX || bVV);
      bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep;
 -    bLastStep        = FALSE;
      bSumEkinhOld     = FALSE;
 -    bDoReplEx        = FALSE;
      bExchanged       = FALSE;
      bNeedRepartition = FALSE;
  
      step     = ir->init_step;
      step_rel = 0;
  
 -    if (ir->nstlist == -1)
 -    {
 -        init_nlistheuristics(&nlh, bGStatEveryStep, step);
 -    }
 +    init_nlistheuristics(&nlh, bGStatEveryStep, step);
  
      if (MULTISIM(cr) && (repl_ex_nst <= 0 ))
      {
          if (bVV && !bStartingFromCpt && !bRerunMD)
          /*  ############### START FIRST UPDATE HALF-STEP FOR VV METHODS############### */
          {
+             wallcycle_start(wcycle, ewcUPDATE);
              if (ir->eI == eiVV && bInitStep)
              {
                  /* if using velocity verlet with full time step Ekin,
                      }
                  }
  
 -                bOK = TRUE;
                  if (!bRerunMD || rerun_fr.bV || bForceUpdate)     /* Why is rerun_fr.bV here?  Unclear. */
                  {
+                     wallcycle_stop(wcycle, ewcUPDATE);
                      update_constraints(fplog, step, NULL, ir, ekind, mdatoms,
                                         state, fr->bMolPBC, graph, f,
                                         &top->idef, shake_vir,
                                         cr, nrnb, wcycle, upd, constr,
                                         TRUE, bCalcVir, vetanew);
+                     wallcycle_start(wcycle, ewcUPDATE);
  
                      if (bCalcVir && bUpdateDoLR && ir->nstcalclr > 1)
                      {
                          /* Correct the virial for multiple time stepping */
                          m_sub(shake_vir, fr->vir_twin_constr, shake_vir);
                      }
 -
 -                    if (!bOK)
 -                    {
 -                        gmx_fatal(FARGS, "Constraint error: Shake, Lincs or Settle could not solve the constrains");
 -                    }
 -
                  }
                  else if (graph)
                  {
                     So we need information from the last step in the first half of the integration */
                  if (bGStat || do_per_step(step-1, nstglobalcomm))
                  {
+                     wallcycle_stop(wcycle, ewcUPDATE);
                      compute_globals(fplog, gstat, cr, ir, fr, ekind, state, state_global, mdatoms, nrnb, vcm,
                                      wcycle, enerd, force_vir, shake_vir, total_vir, pres, mu_tot,
                                      constr, NULL, FALSE, state->box,
                         time step kinetic energy for the pressure (always true now, since we want accurate statistics).
                         b) If we are using EkinAveEkin for the kinetic energy for the temperature control, we still feed in
                         EkinAveVel because it's needed for the pressure */
+                     wallcycle_start(wcycle, ewcUPDATE);
                  }
                  /* temperature scaling and pressure scaling to produce the extended variables at t+dt */
                  if (!bInitStep)
                      {
                          if (bExchanged)
                          {
+                             wallcycle_stop(wcycle, ewcUPDATE);
                              /* We need the kinetic energy at minus the half step for determining
                               * the full step kinetic energy and possibly for T-coupling.*/
                              /* This may not be quite working correctly yet . . . . */
                                              constr, NULL, FALSE, state->box,
                                              top_global, &bSumEkinhOld,
                                              CGLO_RERUNMD | CGLO_GSTAT | CGLO_TEMPERATURE);
+                             wallcycle_start(wcycle, ewcUPDATE);
                          }
                      }
                  }
              {
                  copy_rvecn(cbuf, state->v, 0, state->natoms);
              }
+             wallcycle_stop(wcycle, ewcUPDATE);
          }
  
          /* MRS -- now done iterating -- compute the conserved quantity */
               */
              copy_mat(state->box, lastbox);
  
 -            bOK         = TRUE;
              dvdl_constr = 0;
  
              if (!(bRerunMD && !rerun_fr.bV && !bForceUpdate))
                                         FALSE, bCalcVir,
                                         state->veta);
                  }
 -                if (!bOK)
 -                {
 -                    gmx_fatal(FARGS, "Constraint error: Shake, Lincs or Settle could not solve the constrains");
 -                }
  
 -                if (fr->bSepDVDL && fplog && do_log)
 -                {
 -                    gmx_print_sepdvdl(fplog, "Constraint dV/dl", 0.0, dvdl_constr);
 -                }
                  if (bVV)
                  {
                      /* this factor or 2 correction is necessary
          {
              /* Reset all the counters related to performance over the run */
              reset_all_counters(fplog, cr, step, &step_rel, ir, wcycle, nrnb, walltime_accounting,
 -                               fr->nbv != NULL && fr->nbv->bUseGPU ? fr->nbv->cu_nbv : NULL);
 +                               use_GPU(fr->nbv) ? fr->nbv : NULL);
              wcycle_set_reset_counters(wcycle, -1);
              if (!(cr->duty & DUTY_PME))
              {
      if (pme_loadbal != NULL)
      {
          pme_loadbal_done(pme_loadbal, cr, fplog,
 -                         fr->nbv != NULL && fr->nbv->bUseGPU);
 +                         use_GPU(fr->nbv));
      }
  
      if (shellfc && fplog)
index 6ecdbd5bc6cd676806ec62d709d07ab6acaf4719,c0f12bdb494af9db2b7c4499a061f4870ca0c735..f8d999682db6f1a22c6fe98856fe60483e01c701
   * \author Mark Abraham <mark.j.abraham@gmail.com>
   * \ingroup module_mdrun
   */
 +#include "gmxpre.h"
 +
  #include "moduletest.h"
  
 -#ifdef HAVE_CONFIG_H
 -#  include <config.h>
 -#endif
 +#include "config.h"
  
 -#include "testutils/integrationtests.h"
 -#include "testutils/testoptions.h"
 -#include "testutils/cmdlinetest.h"
 -#include "gromacs/options/options.h"
 +#include "gromacs/gmxpreprocess/grompp.h"
  #include "gromacs/options/basicoptions.h"
 +#include "gromacs/options/options.h"
 +#include "gromacs/utility/basedefinitions.h"
 +#include "gromacs/utility/basenetwork.h"
  #include "gromacs/utility/file.h"
 -#include "gromacs/legacyheaders/network.h"
 -#include "gromacs/legacyheaders/types/simple.h"
 -#include "gromacs/gmxpreprocess/grompp.h"
 +
  #include "programs/mdrun/mdrun_main.h"
  
 +#include "testutils/integrationtests.h"
 +#include "testutils/testoptions.h"
 +#include "testutils/cmdlinetest.h"
 +
  namespace gmx
  {
  namespace test
  namespace
  {
  
+ #if defined(GMX_THREAD_MPI) || defined(DOXYGEN)
  //! Number of tMPI threads for child mdrun call.
- int gmx_unused g_numThreads = 1;
+ int g_numThreads = 1;
+ #endif
+ #if defined(GMX_OPENMP) || defined(DOXYGEN)
  //! Number of OpenMP threads for child mdrun call.
- int gmx_unused g_numOpenMPThreads = 1;
+ int g_numOpenMPThreads = 1;
+ #endif
  //! \cond
  GMX_TEST_OPTIONS(MdrunTestOptions, options)
  {