Merge release-4-5-patches into release-4-6
authorRoland Schulz <roland@utk.edu>
Mon, 26 Nov 2012 20:04:19 +0000 (15:04 -0500)
committerRoland Schulz <roland@utk.edu>
Mon, 26 Nov 2012 20:04:19 +0000 (15:04 -0500)
Conflicts (both trivial):
CMakeLists.txt
src/config.h.cmakein

Change-Id: I363ce1c09c68c2be5aa926e893011d43c8ed3337

1  2 
CMakeLists.txt
src/config.h.cmakein
src/gmxlib/futil.c
src/tools/gmx_cluster.c
src/tools/gmx_hbond.c

diff --combined CMakeLists.txt
index ce8335868921e2e72e00a26bcada535488585264,ce84f6a5e3b23d7dcb20f0fd0d37a74c162b1094..7fb19a985f65c8992c130094d932113b95d61fd4
@@@ -1,17 -1,8 +1,17 @@@
 -cmake_minimum_required(VERSION 2.6)
 +cmake_minimum_required(VERSION 2.8)
  # Keep CMake suitably quiet on Cygwin
  set(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required
  
 -project(Gromacs)
 +# Allows CPack to act differently for normal tools and mdrun (e.g. because of MPI)
 +set(CPACK_COMPONENT_GROUP_TOOLS_DESCRIPTION "All GROMACS executable tools")
 +set(CPACK_COMPONENT_GROUP_MDRUN_DESCRIPTION "GROMACS executable for running simulations")
 +
 +# override bugs on OS X where Cmake picks gcc (GNU) for C instead of system default cc (Clang).
 +if(APPLE)
 +    set(CMAKE_C_COMPILER_INIT "cc")
 +endif(APPLE)
 +
 +project(Gromacs C)
  include(Dart)
  mark_as_advanced(DART_ROOT)
  
@@@ -23,7 -14,7 +23,7 @@@
  # machine with no git. 
  #
  # NOTE: when releasing the "-dev" suffix needs to be stripped off!
 -set(PROJECT_VERSION "4.5.5-dev")
 +set(PROJECT_VERSION "4.6-dev")
  set(CUSTOM_VERSION_STRING ""
      CACHE STRING "Custom version string (if empty, use hard-coded default)")
  mark_as_advanced(CUSTOM_VERSION_STRING)
@@@ -33,57 -24,32 +33,57 @@@ endif (CUSTOM_VERSION_STRING
  set(SOVERSION 6)
  # It is a bit irritating, but this has to be set separately for now!
  SET(CPACK_PACKAGE_VERSION_MAJOR "4")
 -SET(CPACK_PACKAGE_VERSION_MINOR "5")
 -SET(CPACK_PACKAGE_VERSION_PATCH "5")
 +SET(CPACK_PACKAGE_VERSION_MINOR "6")
 +#SET(CPACK_PACKAGE_VERSION_PATCH "0")
 +
 +# The numerical gromacs version. It is 40600 for 4.6.0.
 +# The #define GMX_VERSION in gmx_header_config_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})
  
  # Cmake modules/macros are in a subdirectory to keep this file cleaner
  set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
  
 -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
 +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)
 +
  if(NOT CMAKE_BUILD_TYPE)
 -    set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
 +    set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel Reference." FORCE)
  endif(NOT CMAKE_BUILD_TYPE)
  
  enable_language(C)
  
 +set(GMX_USE_RELATIVE_INSTALL_PATH OFF CACHE STRING "Use relative paths not absolute paths for cmake install. Has only an effect on cpack.")
 +mark_as_advanced(GMX_USE_RELATIVE_INSTALL_PATH)
 +
  set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
  set(CPACK_PACKAGE_VENDOR "gromacs.org")
  set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Gromacs - a toolkit for high-performance molecular simulation")
 -set(CPACK_SET_DESTDIR "ON")
 -set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
 +if (NOT GMX_USE_RELATIVE_INSTALL_PATH)
 +    set(CPACK_SET_DESTDIR "ON")
 +endif()
  set(CPACK_RESOURCE_FILE_WELCOME "${CMAKE_SOURCE_DIR}/admin/InstallWelcome.txt")
  # Its GPL/LGPL, so they do not have to agree to a license for mere usage, but some installers require this...
 -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/admin/InstallLicense.txt")
 +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
  set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/admin/InstallInfo.txt")
 +set(CPACK_SOURCE_IGNORE_FILES ".isreposource;.git;.gitignore")
 +set(CPACK_PROJECT_CONFIG_FILE "${CMAKE_SOURCE_DIR}/CPackInit.cmake")
 +SET(CPACK_SOURCE_INSTALLED_DIRECTORIES "${CMAKE_SOURCE_DIR};/;${CMAKE_BINARY_DIR}/man;man")
 +set(CPACK_PACKAGE_CONTACT "gmx-users@gromacs.org")
  
  #must come after all cpack settings!
  include(CPack)
@@@ -105,84 -71,59 +105,84 @@@ if(CMAKE_HOST_UNIX
              "Hostname of the machine where the cache was generated.")
  endif()
  
 +########################################################################
 +# User input options - enable C++ - before any CXX flags are changed   #
 +########################################################################
 +option(GMX_GPU  "Enable GPU acceleration" ON)
 +option(GMX_OPENMM "Accelerated execution on GPUs through the OpenMM library (rerun cmake after changing to see relevant options)" OFF)
 +option(GMX_FORCE_CXX "Enable C++ compilation even if not necessary" OFF)
 +mark_as_advanced(GMX_FORCE_CXX)
 +if(GMX_GPU OR GMX_OPENMM OR GMX_FORCE_CXX)
 +    enable_language(CXX)
 +endif()
 +set(CMAKE_PREFIX_PATH "" CACHE STRING "Extra locations to search for external libraries and tools (give directory without lib, bin, or include)")
 +
  ########################################################################
  # Fix stupid flags on Windows
  ########################################################################
  SET(SHARED_LIBS_DEFAULT ON) 
 -IF( MSVC )
 +IF( WIN32 AND NOT CYGWIN)
 +  option(GMX_PREFER_STATIC_LIBS "When finding libraries prefer static system libraries (MT instead of MD)!" ON)
 +  mark_as_advanced(GMX_PREFER_STATIC_LIBS)
 +  SET(SHARED_LIBS_DEFAULT OFF)  #is currently not working on Windows
 +
 +  IF (GMX_PREFER_STATIC_LIBS)
 +    #Only setting Debug and Release flags. Others configurations current not used.
      STRING(REPLACE /MD /MT CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
      SET(CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} CACHE STRING "" FORCE)
      STRING(REPLACE /MD /MT CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
 -    SET(CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} CACHE STRING "" FORCE) 
 -    SET(SHARED_LIBS_DEFAULT OFF)      
 -ENDIF()
 +    SET(CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} CACHE STRING "" FORCE)
 +    if(CMAKE_CXX_COMPILER_LOADED)
 +        STRING(REPLACE /MD /MT CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
 +        SET(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} CACHE STRING "" FORCE)
 +        STRING(REPLACE /MD /MT CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
 +        SET(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG} CACHE STRING "" FORCE)
 +    endif()
 +  ENDIF()
  
 -IF( WIN32 AND NOT CYGWIN AND CMAKE_C_COMPILER_ID MATCHES "Intel" )
 -    STRING(REPLACE /GZ /RTC1 CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
 -    SET(CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} CACHE STRING "" FORCE)
 +  #Workaround for cmake bug 13174. Replace deprecated options.
 +  IF( CMAKE_C_COMPILER_ID MATCHES "Intel" )
      STRING(REPLACE /GZ /RTC1 CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
 -    SET(CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} CACHE STRING "" FORCE) 
 -    SET(SHARED_LIBS_DEFAULT OFF)      
 +    SET(CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} CACHE STRING "" FORCE)
 +  ENDIF()
 +  IF( CMAKE_CXX_COMPILER_ID MATCHES "Intel" AND CMAKE_CXX_COMPILER_LOADED)
 +    STRING(REPLACE /GZ /RTC1 CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
 +    STRING(REPLACE /GX /EHsc CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
 +    SET(CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG} CACHE STRING "" FORCE)
 +
 +    STRING(REPLACE /GX /EHsc CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
 +    SET(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} CACHE STRING "" FORCE)
 +  ENDIF()
  ENDIF()
  
 -set(GMX_EXTRA_LIBRARIES)
 -
 -
 -
 -######################################################################
 -# compiler tests
 -# these need ot be done early (before further tests).
 -#####################################################################
 -
 -include(CheckCCompilerFlag)
 -include(CheckCXXCompilerFlag)
 -
 -include(gmxCFlags)
 -gmx_c_flags()
  
  ########################################################################
  # User input options                                                   #
  ########################################################################
  option(GMX_DOUBLE "Use double precision (much slower, use only if you really need it)" OFF)
  option(GMX_MPI    "Build a parallel (message-passing) version of GROMACS" OFF)
 -option(GMX_THREADS    "Build a parallel (thread-based) version of GROMACS (cannot be combined with MPI yet)" ON)
 +option(GMX_THREAD_MPI  "Build a thread-MPI-based multithreaded version of GROMACS (not compatible with MPI)" ON)
  option(GMX_SOFTWARE_INVSQRT "Use GROMACS software 1/sqrt" ON)
  mark_as_advanced(GMX_SOFTWARE_INVSQRT)
  option(GMX_POWERPC_INVSQRT "Use PowerPC hardware 1/sqrt" OFF)
  mark_as_advanced(GMX_POWERPC_INVSQRT)
  option(GMX_FAHCORE "Build a library with mdrun functionality" OFF)
  mark_as_advanced(GMX_FAHCORE)
 -option(GMX_OPENMM "Accelerated execution on GPUs through the OpenMM library (rerun cmake after changing to see relevant options)" OFF)
 -set(GMX_ACCELERATION "auto" 
 -    CACHE STRING "Accelerated kernels. Pick one of: auto, none, SSE, BlueGene, Power6, ia64, altivec, fortran")
 +
 +include(gmxDetectAcceleration)
 +if(NOT DEFINED GMX_CPU_ACCELERATION)
 +    if(CMAKE_CROSSCOMPILING)
 +        set(GMX_SUGGESTED_CPU_ACCELERATION "None")
 +    else(CMAKE_CROSSCOMPILING)
 +        gmx_detect_acceleration(GMX_SUGGESTED_CPU_ACCELERATION)
 +    endif(CMAKE_CROSSCOMPILING)
 +endif(NOT DEFINED GMX_CPU_ACCELERATION)
 +
 +set(GMX_CPU_ACCELERATION "@GMX_SUGGESTED_CPU_ACCELERATION@"
 +    CACHE STRING "Accelerated CPU kernels. Pick one of: None, SSE2, SSE4.1, AVX_128_FMA, AVX_256, BlueGene, Power6, Fortran")
  
  set(GMX_FFT_LIBRARY "fftw3" 
 -    CACHE STRING "FFT library choices: fftw3,fftw2,mkl,fftpack[built-in]")
 +    CACHE STRING "FFT library choices: fftw3,mkl,fftpack[built-in]")
  option(GMX_DISABLE_FFTW_MEASURE 
         "Do not optimize FFTW setups (not needed with SSE)" OFF)
  mark_as_advanced(GMX_DISABLE_FFTW_MEASURE)
@@@ -190,81 -131,28 +190,81 @@@ set(GMX_QMMM_PROGRAM "none
      CACHE STRING "QM package choices: none,gaussian,mopac,gamess,orca")
  option(GMX_BROKEN_CALLOC "Work around broken calloc()" OFF)
  mark_as_advanced(GMX_BROKEN_CALLOC)
 -option(BUILD_SHARED_LIBS "Enable shared libraries (can be problematic with MPI, Windows)" ${SHARED_LIBS_DEFAULT})
  option(GMX_MPI_IN_PLACE "Enable MPI_IN_PLACE for MPIs that have it defined" ON)
  mark_as_advanced(GMX_MPI_IN_PLACE)
 -option(GMX_DLOPEN "Compile with dlopen, needed to read VMD supported file formats" ON)
 -mark_as_advanced(GMX_DLOPEN)
 -
 +option(GMX_LOAD_PLUGINS "Compile with plugin support, needed to read VMD supported file formats" ON)
 +mark_as_advanced(GMX_LOAD_PLUGINS)
  
 -option(GMX_IA32_ASM "Add SSE assembly files for IA32" OFF)
 -mark_as_advanced(GMX_IA32_ASM)
 -option(GMX_X86_64_ASM "Add SSE assembly files for X86_64" OFF)
 -mark_as_advanced(GMX_X86_64_ASM)
 +option(GMX_OPENMP "Enable OpenMP-based multithreading" ON)
  
  option(USE_VERSION_H "Generate development version string/information" ON)
  mark_as_advanced(USE_VERSION_H)
  
  option(GMX_DEFAULT_SUFFIX "Use default suffixes for GROMACS binaries and libs (_d for double, _mpi for MPI; rerun cmake after changing to see relevant options)" ON)
  
 -if(UNIX AND NOT APPLE)
 -    option(GMX_PREFER_STATIC_LIBS "When finding libraries prefer \".a\" static archives (NOTE: this is enabled only for UNIX (excluding APPLE) platforms but it might not always work!" OFF)
 +if(UNIX)
 +    option(GMX_PREFER_STATIC_LIBS "When finding libraries prefer static archives (not available on non-*nix platforms and it will only work if static versions of external dependencies are available and found)!" OFF)
      mark_as_advanced(GMX_PREFER_STATIC_LIBS)
  endif()
  
 +option(GMX_CYCLE_SUBCOUNTERS "Enable cycle subcounters to get a more detailed cycle timings" OFF)
 +mark_as_advanced(GMX_CYCLE_SUBCOUNTERS)
 +
 +######################################################################
 +# Compiler tests
 +# These need to be done early (before further tests).
 +#####################################################################
 +
 +# The cmake/Check{C,CXX}CompilerFlag.cmake files in the GROMACS distribution
 +# are used with permission from CMake v2.8.9 so that GROMACS can detect
 +# invalid options with the Intel Compilers.
 +# These files should be removed from the source tree when a CMake version that
 +# includes the features in question becomes required for building GROMACS.
 +include(CheckCCompilerFlag)
 +if(CMAKE_CXX_COMPILER_LOADED)
 +    include(CheckCXXCompilerFlag)
 +endif()
 +
 +# OpenMP check must come before other CFLAGS!
 +if(GMX_OPENMP)
 +    find_package(OpenMP)
 +    if(OPENMP_FOUND)
 +        # CMake on Windows doesn't support linker flags passed to target_link_libraries
 +        # (i.e. it treats /openmp as \openmp library file). Also, no OpenMP linker flags are needed.
 +        if(NOT (WIN32 AND NOT CYGWIN))
 +            if(CMAKE_COMPILER_IS_GNUCC AND GMX_PREFER_STATIC_OPENMP)
 +                set(OpenMP_LINKER_FLAGS "-Wl,-static -lgomp -lrt -Wl,-Bdynamic -lpthread")
 +                set(OpenMP_SHARED_LINKER_FLAGS "")
 +            else()
 +                # Only set a linker flag if the user didn't set them manually
 +                if(NOT DEFINED OpenMP_LINKER_FLAGS)
 +                    set(OpenMP_LINKER_FLAGS "${OpenMP_C_FLAGS}")
 +                endif()
 +                if(NOT DEFINED OpenMP_SHARED_LINKER_FLAGS)
 +                    set(OpenMP_SHARED_LINKER_FLAGS "${OpenMP_C_FLAGS}")
 +                endif()
 +            endif()
 +        endif()
 +    else(OPENMP_FOUND)
 +        message(WARNING
 +                "The compiler you are using does not support OpenMP parallelism. This might hurt your performance a lot, in particular with GPUs. Try using a more recent version, or a different compiler. For now, we are proceeding by turning off OpenMP.")
 +        set(GMX_OPENMP OFF CACHE STRING "Whether GROMACS will use OpenMP parallelism." FORCE)
 +    endif(OPENMP_FOUND)
 +endif()
 +
 +
 +include(gmxCFlags)
 +gmx_c_flags()
 +
 +include(gmxGetCompilerInfo)
 +get_compiler_version()
 +
 +# gcc 4.4.x is buggy and crashes when compiling some files with O3 and OpenMP on.
 +# Detect here whether applying a workaround is needed and will apply it later
 +# on the affected files.
 +include(gmxGCC44O3BugWorkaround)
 +gmx_check_gcc44_bug_workaround_needed(GMX_USE_GCC44_BUG_WORKAROUND)
 +
  ########################################################################
  # Set up binary and library suffixing 
  ########################################################################
@@@ -283,22 -171,17 +283,22 @@@ if (GMX_DEFAULT_SUFFIX
      set (GMX_LIBS_SUFFIX "${GMX_LIBS_SUFFIX}_d")
    endif(GMX_DOUBLE)
    if (GMX_OPENMM)
 -    set (GMX_BINARY_SUFFIX "-gpu")
 -    set (GMX_LIBS_SUFFIX "_gpu")
 +    set (GMX_BINARY_SUFFIX "-openmm")
 +    set (GMX_LIBS_SUFFIX "_openmm")
    endif(GMX_OPENMM)
    mark_as_advanced(FORCE GMX_BINARY_SUFFIX GMX_LIBS_SUFFIX)
 -  message(STATUS "Using default binary suffix: \"${GMX_BINARY_SUFFIX}\"")    
 -  message(STATUS "Using default library suffix: \"${GMX_LIBS_SUFFIX}\"") 
 +  if (NOT SUFFIX_QUIETLY)
 +    message(STATUS "Using default binary suffix: \"${GMX_BINARY_SUFFIX}\"")
 +    message(STATUS "Using default library suffix: \"${GMX_LIBS_SUFFIX}\"")
 +  endif (NOT SUFFIX_QUIETLY)
  else(GMX_DEFAULT_SUFFIX)
    mark_as_advanced(CLEAR GMX_BINARY_SUFFIX GMX_LIBS_SUFFIX)
 -  message(STATUS "Using manually set binary suffix: \"${GMX_BINARY_SUFFIX}\"")    
 -  message(STATUS "Using manually set library suffix: \"${GMX_LIBS_SUFFIX}\"")
 +  if (NOT SUFFIX_QUIETLY)
 +    message(STATUS "Using manually set binary suffix: \"${GMX_BINARY_SUFFIX}\"")
 +    message(STATUS "Using manually set library suffix: \"${GMX_LIBS_SUFFIX}\"")
 +  endif (NOT SUFFIX_QUIETLY)
  endif(GMX_DEFAULT_SUFFIX)
 +set(SUFFIX_QUIETLY TRUE CACHE INTERNAL "")
  
  set(PKG_CFLAGS "")
  if(GMX_DOUBLE)
@@@ -314,12 -197,71 +314,12 @@@ endif(GMX_POWERPC_INVSQRT
  ########################################################################
  #Process MPI settings
  ########################################################################
 -include(CheckCSourceCompiles) # for gmxTestMPI_IN_PLACE
 -if(GMX_MPI)
 -    if(GMX_THREADS)
 -        #message(FATAL_ERROR "Thread-based parallelization conflicts with MPI.")
 -        set(GMX_THREADS OFF CACHE BOOL 
 -            "Thread-based parallelization conflicts with MPI." FORCE)
 -    endif(GMX_THREADS)
 -    find_package(MPI)
 -    if(MPI_FOUND)
 -        set(GROMACS_C_FLAGS ${GROMACS_FLAGS} ${MPI_COMPILE_FLAGS})
 -      set(GROMACS_LINKER_FLAGS ${GROMACS_LINKER_FLAGS} ${MPI_LINK_FLAGS})
 -        
 -        include_directories(${MPI_INCLUDE_PATH})
 -        list(APPEND GMX_EXTRA_LIBRARIES ${MPI_LIBRARIES})
 -        if(GMX_FAHCORE)
 -            add_definitions( -DMPI ) #for FAHCORE
 -        endif(GMX_FAHCORE)
 -        include(gmxTestMPI_IN_PLACE)
 -        if (GMX_MPI_IN_PLACE)
 -            gmx_test_mpi_in_place(MPI_IN_PLACE_EXISTS)
 -        endif (GMX_MPI_IN_PLACE)
 -
 -      # test for unsuitable versions of OpenMPI
 -      exec_program(${MPIEXEC}
 -        ARGS --version
 -        OUTPUT_VARIABLE MPI_TYPE
 -        RETURN_VALUE MPI_EXEC_RETURN)
 -      if(MPI_EXEC_RETURN EQUAL 0)
 -        if(MPI_TYPE MATCHES "Open MPI|OpenRTE")
 -          string(REGEX MATCH "[0-9]+\\.[0-9]*\\.?[0-9]*" MPI_VERSION ${MPI_TYPE})
 -          if(MPI_VERSION VERSION_LESS "1.4.1")
 -            MESSAGE(WARNING "
 -            There are known problems with OpenMPI version < 1.4.1.
 -            Please consider updating your OpenMPI.")
 -          endif(MPI_VERSION VERSION_LESS "1.4.1")
 -          unset(MPI_VERSION)
 -        else(MPI_TYPE MATCHES "Open MPI|OpenRTE")
 -          # This is not OpenMPI, so give the old generic warning message
 -          MESSAGE(WARNING "
 -            There are known problems with some MPI implementations:
 -                     MVAPICH2 version <= 1.4.1
 -            Please consider updating your MPI if applicable.")
 -        endif(MPI_TYPE MATCHES "Open MPI|OpenRTE")
 -        unset(MPI_TYPE)
 -      endif(MPI_EXEC_RETURN EQUAL 0)
 -    else(MPI_FOUND)
 -        message(FATAL_ERROR "MPI support requested, but no MPI compiler found.")
 -    endif(MPI_FOUND)
 -    include(gmxTestCatamount)
 -    gmx_test_catamount(GMX_CRAY_XT3)
 -    if(GMX_CRAY_XT3)
 -        set(PKG_CFLAGS "${PKG_CFLAGS} -DGMX_CRAY_XT3")
 -        set(GMX_NO_SYSTEM 1)
 -        set(GMX_NO_NICE 1)
 -    endif(GMX_CRAY_XT3)
 -    set(GMX_LIB_MPI 1)
 -    set(PKG_CFLAGS "${PKG_CFLAGS} -DGMX_LIB_MPI")
 -endif(GMX_MPI)
 -
 +include(gmxManageMPI)
  
  #######################################################################
  # Check for options incompatible with OpenMM build                    #
  #######################################################################
  if(GMX_OPENMM)
 -    cmake_minimum_required(VERSION 2.6.4)
      # we'll use the built-in fft to avoid unnecessary dependencies
      string(TOUPPER ${GMX_FFT_LIBRARY} GMX_FFT_LIBRARY)
      if(NOT ${GMX_FFT_LIBRARY} STREQUAL "FFTPACK")
      if(GMX_MPI)
          message(FATAL_ERROR "The OpenMM build is not compatible with MPI!")
      endif(GMX_MPI)
 -    if(GMX_THREADS)
 -        message(STATUS "Threads are  not compatible with OpenMM build, disabled!")
 -        set(GMX_THREADS OFF CACHE BOOL 
 -              "Threads are not compatible with OpenMM build, disabled!" FORCE)
 -    endif(GMX_THREADS)
 +    if(GMX_THREAD_MPI)
 +        message(STATUS "Thread-MPI not compatible with OpenMM, disabled!")
 +        set(GMX_THREAD_MPI OFF CACHE BOOL
 +              "Thread-MPI not compatible with OpenMM build, disabled!" FORCE)
 +    endif(GMX_THREAD_MPI)
 +    if(GMX_OPENMP)
 +        message(STATUS "OpenMP multithreading not compatible with OpenMM, disabled")
 +        set(GMX_OPENMP OFF CACHE BOOL
 +            "OpenMP multithreading not compatible with OpenMM, disabled!" FORCE)
 +    endif()
      if(GMX_SOFTWARE_INVSQRT)
          set(GMX_SOFTWARE_INVSQRT OFF CACHE STRING 
                  "The OpenMM build does not need GROMACS software 1/sqrt!" FORCE)
      endif(GMX_SOFTWARE_INVSQRT)
 -    string(TOUPPER ${GMX_ACCELERATION} GMX_ACCELERATION)
 -    if(NOT GMX_ACCELERATION STREQUAL "NONE")
 -        message(STATUS "Switching off CPU-based acceleration, the OpenMM build does not support/need any!")   
 -        set(GMX_ACCELERATION "none" CACHE STRING 
 -              "Switching off CPU-based acceleration, the OpenMM build does not support/need any!" FORCE)
 +    string(TOUPPER ${GMX_CPU_ACCELERATION} GMX_CPU_ACCELERATION)
 +    if(NOT GMX_CPU_ACCELERATION STREQUAL "NONE")
 +        message(STATUS "Switching off CPU-based acceleration, the OpenMM build does not support/need any!")
 +        set(GMX_CPU_ACCELERATION "None" CACHE STRING
 +            "Switching off CPU-based acceleration, the OpenMM build does not support/need any!" FORCE)
      endif()
      if(GMX_FAHCORE)
          message(FATAL_ERROR "The OpenMM build does not support FAH build!")
          message(FATAL_ERROR  "The OpenMM-build does not support double precision calculations!")
      endif()
      # mark as advanced the unused variables
 -    mark_as_advanced(FORCE GMX_ACCELERATION GMX_MPI GMX_FFT_LIBRARY 
 -        GMX_QMMM_PROGRAM GMX_THREADS GMX_DOUBLE)
 +    mark_as_advanced(FORCE GMX_CPU_ACCELERATION GMX_MPI GMX_FFT_LIBRARY 
 +        GMX_QMMM_PROGRAM GMX_THREAD_MPI GMX_DOUBLE)
  else(GMX_OPENMM)
 -     mark_as_advanced(CLEAR GMX_ACCELERATION GMX_MPI GMX_FFT_LIBRARY 
 -        GMX_QMMM_PROGRAM GMX_THREADS GMX_DOUBLE)   
 +     mark_as_advanced(CLEAR GMX_CPU_ACCELERATION GMX_MPI GMX_FFT_LIBRARY 
 +        GMX_QMMM_PROGRAM GMX_THREAD_MPI GMX_DOUBLE)
  endif(GMX_OPENMM)
  
  
@@@ -387,8 -324,13 +387,8 @@@ check_include_files(sys/stat.h   HAVE_S
  check_include_files(sys/time.h   HAVE_SYS_TIME_H)
  check_include_files(rpc/rpc.h    HAVE_RPC_RPC_H)
  check_include_files("rpc/rpc.h;rpc/xdr.h"    HAVE_RPC_XDR_H)
 -# SSE support
 -check_include_files(xmmintrin.h  HAVE_XMMINTRIN_H)
 -check_include_files(emmintrin.h  HAVE_EMMINTRIN_H)
 -check_include_files(pmmintrin.h  HAVE_PMMINTRIN_H)
 -check_include_files(smmintrin.h  HAVE_SMMINTRIN_H)
  check_include_files(io.h               HAVE_IO_H)
 -
 +check_include_files(sched.h      HAVE_SCHED_H)
  
  include(CheckFunctionExists)
  check_function_exists(strcasecmp        HAVE_STRCASECMP)
@@@ -405,14 -347,6 +405,13 @@@ check_function_exists(fsyn
  check_function_exists(_fileno           HAVE__FILENO)
  check_function_exists(fileno            HAVE_FILENO)
  check_function_exists(_commit           HAVE__COMMIT)
- check_function_exists(lstat             HAVE_LSTAT)
 +check_function_exists(sigaction         HAVE_SIGACTION)
 +check_function_exists(sysconf           HAVE_SYSCONF)
 +check_function_exists(sched_setaffinity HAVE_SCHED_SETAFFINITY)
 +check_function_exists(sched_getaffinity HAVE_SCHED_GETAFFINITY)
 +check_function_exists(rsqrt             HAVE_RSQRT)
 +check_function_exists(rsqrtf            HAVE_RSQRTF)
 +check_function_exists(sqrtf             HAVE_SQRTF)
  
  include(CheckLibraryExists)
  check_library_exists(m sqrt "" HAVE_LIBM)
@@@ -472,22 -406,27 +471,22 @@@ test_big_endian(GMX_INTEGER_BIG_ENDIAN
  ########################################################################
  # Find external packages                                               #
  ########################################################################
 -if(UNIX AND NOT APPLE)
 +if(UNIX)
      if(GMX_PREFER_STATIC_LIBS)
 -        SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
 -        if(BUILD_SHARED_LIBS)
 -            message(WARNING "Static libraries requested, the GROMACS libraries will also be build static (BUILD_SHARED_LIBS=OFF)")
 -            set(BUILD_SHARED_LIBS OFF CACHE BOOL "Enable shared libraries (can be problematic with MPI, Windows)" FORCE)
 +        # On Linux .a is the static library suffix, on Mac OS X .lib can also
 +        # be used, so we'll add both to the preference list.
 +        SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib;.a" ${CMAKE_FIND_LIBRARY_SUFFIXES})
 +        if(SHARED_LIBS_DEFAULT)
 +            if(BUILD_SHARED_LIBS) #Warn the user about the combination. But don't overwrite the request.
 +                message(WARNING "Static libraries requested, and shared Gromacs libraries requested.")
 +            elseif(NOT DEFINED BUILD_SHARED_LIBS) #Change default to OFF. Don't warn if it's already off.
 +                message(WARNING "Static libraries requested, the GROMACS libraries will also be build static (BUILD_SHARED_LIBS=OFF)")
 +                set(SHARED_LIBS_DEFAULT OFF)
 +            endif()
          endif()
      endif()
  endif()
 -
 -option(GMX_XML "Use libxml2 to parse xml files" ON)
 -if (GMX_XML)
 -  find_package(LibXml2)
 -  set(PKG_XML "")
 -  if(LIBXML2_FOUND)
 -    include_directories(${LIBXML2_INCLUDE_DIR})
 -    set(PKG_XML libxml-2.0)
 -    set(XML_LIBRARIES ${LIBXML2_LIBRARIES})
 -    set(HAVE_LIBXML2 1)
 -  endif(LIBXML2_FOUND)
 -endif(GMX_XML)
 +option(BUILD_SHARED_LIBS "Enable shared libraries (can be problematic with MPI, Windows)" ${SHARED_LIBS_DEFAULT})
  
  option(GMX_GSL "Add support for gsl" OFF)
  if (GMX_GSL)
@@@ -509,15 -448,16 +508,15 @@@ if (GMX_X11
        endif(X11_FOUND)
  endif(GMX_X11)
  
 -if(GMX_THREADS)
 -    set(PKG_CFLAGS "${PKG_CFLAGS} -DGMX_THREADS")
 -    include(ThreadMPI)
 -    set(THREAD_MPI_LIB thread_mpi)
 +include(ThreadMPI)
 +set(THREAD_MPI_LIB thread_mpi)
 +if(GMX_THREAD_MPI)
 +    tmpi_get_source_list(THREAD_MPI_SRC)
 +    set(PKG_CFLAGS "${PKG_CFLAGS} -DGMX_THREAD_MPI")
      set(GMX_MPI 1)
 -    string(TOUPPER ${GMX_FFT_LIBRARY} ${GMX_FFT_LIBRARY})
 -    if(${GMX_FFT_LIBRARY} STREQUAL "FFTW2")
 -        message(FATAL_ERROR "FFTW2 can't be used with threads. Try fftw3 or mkl.")
 -    endif()
 -endif(GMX_THREADS)
 +else(GMX_THREAD_MPI)
 +    tmpi_get_source_list(THREAD_MPI_SRC NOMPI)
 +endif(GMX_THREAD_MPI)
  
  if(GMX_OPENMM)
      set(CUDA_BUILD_EMULATION OFF)
      find_package(OpenMM) 
  endif(GMX_OPENMM)
  
 +
 +if(GMX_GPU)
 +    if(GMX_DOUBLE)
 +        message(WARNING "GPU acceleration is not available in double precision, disabled!")
 +        set(GMX_GPU OFF CACHE BOOL "Enable GPU acceleration" FORCE)
 +    endif()
 +endif(GMX_GPU)
 +
 +if(GMX_GPU)
 +
 +    # We support CUDA >=v3.2 on *nix, but <= v4.1 doesn't work with MSVC
 +    if(MSVC)
 +        find_package(CUDA 4.1)
 +    else()
 +        find_package(CUDA 3.2)
 +    endif()
 +
 +    if (NOT EXISTS ${CUDA_TOOLKIT_ROOT_DIR})
 +        message(FATAL_ERROR "
 +    mdrun supports native GPU acceleration on NVIDIA hardware with compute
 +    capability >=2.0. This requires the NVIDIA CUDA library, which was not
 +    found; the location can be hinted by setting CUDA_TOOLKIT_ROOT_DIR as
 +    a CMake option (It does not work as an environment variable).
 +    The typical location would be /usr/local/cuda.
 +
 +    CPU or GPU acceleration can be selected at runtime, but if you are
 +    sure you can not make use of GPU acceleration, disable it by setting
 +    the CMake variable GMX_GPU=OFF.")
 +    endif()
 +
 +    if(NOT GMX_OPENMP)
 +        message(WARNING "
 +    In order to use GPU acceleration efficiently, mdrun requires OpenMP multithreading.
 +    Without OpenMP only a single CPU core per GPU can be used which is suboptimal.
 +    Note that with MPI multiple processes can be forced to use a single GPU, but this
 +    typically inefficient. Note that you need to set both C and C++ compilers that
 +    support OpenMP (CC and CXX environment variables, respectively) when using GPUs.")
 +    endif()
 +
 +    include(gmxManageNvccConfig)
 +
 +    # Check whether we can use atomic operations needed for polling wait for GPU
 +    # (to avoid the cudaStreamSynchronize + ECC bug).
 +    # With thread-MPI testing atomics has already been carried out, but without
 +    # thread-MPI we need to invoke the atomics test independently.
 +    if (NOT GMX_THREAD_MPI)
 +        set(TEST_TMPI_ATOMICS_ONLY ON CACHE INTERNAL
 +            "Test only the atomic operations of thread-MPI.")
 +        include(ThreadMPI)
 +    endif()
 +
 +    # Version info (semicolon used as line separator) for nvcc.
 +    get_nvcc_version_info()
 +
 +endif()
 +# Annoyingly enough, FindCUDA leaves a few variables behind as non-advanced.
 +# We need to mark these advanced outside the conditional, otherwise, if the user
 +# tuns GMX_GPU=OFF after a failed cmake pass, these variables will be left behind.
 +mark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_SDK_ROOT_DIR CUDA_VERBOSE_BUILD)
 +
  if(APPLE)
     find_library(ACCELERATE_FRAMEWORK Accelerate)
     list(APPEND GMX_EXTRA_LIBRARIES ${ACCELERATE_FRAMEWORK})
@@@ -598,36 -478,29 +597,36 @@@ if(CYGWIN
      set(GMX_CYGWIN 1)
  endif(CYGWIN)
  
 +if(WIN32 AND NOT CYGWIN)
 +    set(GMX_NATIVE_WINDOWS 1)
 +endif()
 +
  # only bother with finding git and using version.h if the source is a git repo
  if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
      if(USE_VERSION_H)
          # We need at least git v1.5.3 be able to parse git's date output. If not
 -        # fund or the version is too small, we can't generate version information.
 -        find_package(Git 1.5.3)
 -        # this should at some point become VERSION_LESS
 -        if(NOT Git_FOUND OR Git_VERSION STRLESS "1.5.3")
 -            message("No compatible git version found, won't be able to generate proper development version information.")
 -            set(USE_VERSION_H OFF)
 +        # found or the version is too small, we can't generate version information.
 +        find_package(Git)
 +
 +      # Find out the git version
 +      if(GIT_FOUND AND NOT GIT_VERSION)
 +        execute_process(COMMAND ${GIT_EXECUTABLE} "--version"
 +            OUTPUT_VARIABLE _exec_out
 +            OUTPUT_STRIP_TRAILING_WHITESPACE)
 +        string(REGEX REPLACE "git version (.*)" "\\1" GIT_VERSION ${_exec_out})
 +        set(GIT_VERSION ${GIT_VERSION} CACHE STRING "Git version")
 +        mark_as_advanced(GIT_VERSION)
 +      endif()
 +
 +        if(NOT GIT_FOUND OR GIT_VERSION VERSION_LESS "1.5.3")
 +          message("No compatible git version found, won't be able to generate proper development version information.")
 +          set(USE_VERSION_H OFF)
          endif()
      endif()
  else()
      set(USE_VERSION_H OFF)
  endif()
  
 -if (GMX_DLOPEN)
 -    list(APPEND GMX_EXTRA_LIBRARIES ${CMAKE_DL_LIBS})
 -    set(PKG_DL_LIBS "-l${CMAKE_DL_LIBS}")
 -else(GMX_DLOPEN)
 -    set(PKG_DL_LIBS)
 -endif (GMX_DLOPEN)
 -
  ########################################################################
  # Generate development version info for cache
  ########################################################################
  
  add_definitions( -DHAVE_CONFIG_H )
  include_directories(${CMAKE_BINARY_DIR}/src)
 +include_directories(${CMAKE_BINARY_DIR}/include)
  include_directories(${CMAKE_SOURCE_DIR}/include)
  
 -include(gmxCheckBuildUserTime)
 -gmx_check_build_user_time(BUILD_TIME BUILD_USER BUILD_MACHINE)
 +include(gmxTestInlineASM)
 +gmx_test_inline_asm_gcc_x86(GMX_X86_GCC_INLINE_ASM)
 +
 +include(gmxSetBuildInformation)
 +gmx_set_build_information()
 +if(BUILD_CPU_FEATURES MATCHES "rdtscp" AND NOT GMX_DISTRIBUTABLE_BUILD)
 +    # The timestep counter headers do not include config.h
 +    add_definitions(-DHAVE_RDTSCP)
 +endif(BUILD_CPU_FEATURES MATCHES "rdtscp" AND NOT GMX_DISTRIBUTABLE_BUILD)
  
  include(gmxTestFloatFormat)
  gmx_test_float_format(GMX_FLOAT_FORMAT_IEEE754 
@@@ -662,13 -527,14 +661,13 @@@ include(gmxTestLargeFiles
  gmx_test_large_files(GMX_LARGEFILES)
  
  include(gmxTestSignal)
 -gmx_test_retsigtype(RETSIGTYPE)
  gmx_test_sigusr1(HAVE_SIGUSR1)
  
  include(gmxTestInline)
  gmx_test_inline(INLINE_KEYWORD)
  
  include(gmxTestRestrict)
 -gmx_test_inline(RESTRICT_KEYWORD)
 +gmx_test_restrict(RESTRICT_KEYWORD)
  
  include(gmxTestPipes)
  gmx_test_pipes(HAVE_PIPES)
@@@ -678,6 -544,22 +677,6 @@@ gmx_test_isfinite(HAVE_ISFINITE
  gmx_test__isfinite(HAVE__ISFINITE)
  gmx_test__finite(HAVE__FINITE)
  
 -include(gmxTestInlineASM)
 -gmx_test_inline_asm_gcc_x86(GMX_X86_GCC_INLINE_ASM)
 -gmx_test_inline_asm_msvc_x86(GMX_X86_MSVC_INLINE_ASM)
 -
 -# turn on SSE if supported with reasonable defaults.
 -if (${GMX_ACCELERATION} STREQUAL "auto" AND NOT GMX_OPENMM)
 -  if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86|x64|x86_64|AMD64|amd64)" OR CYGWIN)
 -
 -    set(GMX_ACCELERATION "SSE" CACHE STRING "Accelerated kernels. Pick one of: auto, none, SSE, BlueGene, Power6, ia64, altivec, fortran" FORCE)
 -    
 -    # Determine the assembler/compiler to use
 -  else()
 -    set(GMX_ACCELERATION "none" CACHE STRING "Accelerated kernels. Pick one of: auto, none, SSE, BlueGene, Power6, ia64, altivec, fortran" FORCE)
 -  endif()
 -endif (${GMX_ACCELERATION} STREQUAL "auto" AND NOT GMX_OPENMM)
 -
  include(gmxTestXDR)
  gmx_test_xdr(GMX_SYSTEM_XDR)
  if(NOT GMX_SYSTEM_XDR)
  endif(NOT GMX_SYSTEM_XDR)
  
  # Process nonbonded accelerated kernels settings
 -string(TOUPPER ${GMX_ACCELERATION} ${GMX_ACCELERATION})
 -if(${GMX_ACCELERATION} STREQUAL "NONE")
 -  # nothing to do
 -elseif(${GMX_ACCELERATION} STREQUAL "SSE")
 -    
 -    if (GMX_64_BIT)
 -      set(GMX_X86_64_ASM ON CACHE BOOL "Add SSE assembly files for x86_64" FORCE)
 -    else (GMX_64_BIT)
 -      set(GMX_IA32_ASM ON CACHE BOOL "Add SSE assembly files for i386" FORCE)
 -    endif (GMX_64_BIT)
 -
 -    if( WIN32 AND NOT CYGWIN )
 -      option(GMX_ASM_USEASM_NASM "Use Nasm for assembly instead of compiler (necessary on windows)" ON)
 -    else()
 -      option(GMX_ASM_USEASM_NASM "Use Nasm for assembly instead of compiler (necessary on windows)" OFF)
 +string(TOUPPER ${GMX_CPU_ACCELERATION} ${GMX_CPU_ACCELERATION})
 +if(${GMX_CPU_ACCELERATION} STREQUAL "NONE")
 +    # nothing to do
 +elseif(${GMX_CPU_ACCELERATION} STREQUAL "SSE2")
 +
 +    GMX_TEST_CFLAG(GNU_SSE2_CFLAG "-msse2" GROMACS_C_FLAGS)
 +    if(NOT GNU_SSE2_CFLAG)
 +        GMX_TEST_CFLAG(MSVC_SSE2_CFLAG "/arch:SSE2" GROMACS_C_FLAGS)
 +    endif(NOT GNU_SSE2_CFLAG)
 +
 +    if (CMAKE_CXX_COMPILER_LOADED)
 +        GMX_TEST_CXXFLAG(GNU_SSE2_CXXFLAG "-msse2" GROMACS_CXX_FLAGS)
 +        if(NOT GNU_SSE2_CXXFLAG)
 +            GMX_TEST_CXXFLAG(MSVC_SSE2_CXXFLAG "/arch:SSE2" GROMACS_CXX_FLAGS)
 +        endif(NOT GNU_SSE2_CXXFLAG)
 +    endif()
 +
 +    # We dont warn for lacking SSE2 flag support, since that is probably standard today.
 +
 +    # Only test the include after we have tried to add the correct flag for SSE2 support
 +    check_include_file(emmintrin.h  HAVE_EMMINTRIN_H ${GROMACS_C_FLAGS})
 +
 +    if(NOT HAVE_EMMINTRIN_H)
 +        message(FATAL_ERROR "Cannot find emmintrin.h, which is required for SSE2 intrinsics support.")
 +    endif(NOT HAVE_EMMINTRIN_H)
 +
 +    set(GMX_CPU_ACCELERATION_X86_SSE2 1)
 +    # The user should not be able to set this orthogonally to the acceleration
 +    set(GMX_X86_SSE2 1)
 +    if (NOT ACCELERATION_QUIETLY)
 +      message(STATUS "Enabling SSE2 Gromacs acceleration, and it will help compiler optimization.")
      endif()
 -      mark_as_advanced(GMX_ASM_USEASM_NASM)
 -
 -    if (NOT GMX_64_BIT)
 -        # for 32-bit compiles, we might need to turn on sse 
 -        CHECK_C_COMPILER_FLAG("-msse2" XFLAGS_SSE)
 -        if (XFLAGS_SSE)
 -            set(GROMACS_C_FLAGS "-msse2 ${GROMACS_C_FLAGS}")
 -        endif (XFLAGS_SSE)
 -        CHECK_CXX_COMPILER_FLAG("-msse2" XXFLAGS_SSE)
 -        if (XXFLAGS_SSE)
 -            set(GROMACS_CXX_FLAGS "-msse2 ${GROMACS_CXX_FLAGS}")
 -        endif (XXFLAGS_SSE)
 -    endif (NOT GMX_64_BIT)
 -
 -    if(GMX_IA32_ASM)
 -      if(GMX_DOUBLE)
 -        set(GMX_IA32_SSE2 1)
 -      else()
 -       set(GMX_IA32_SSE 1)
 -      endif()
 -    elseif(GMX_X86_64_ASM)
 -      if(GMX_DOUBLE)
 -       set(GMX_X86_64_SSE2 1)
 -      else()
 -        set(GMX_X86_64_SSE 1)
 -      endif()
 +
 +elseif(${GMX_CPU_ACCELERATION} STREQUAL "SSE4.1")
 +
 +    GMX_TEST_CFLAG(GNU_SSE4_CFLAG "-msse4.1" GROMACS_C_FLAGS)
 +    if (NOT GNU_SSE4_CFLAG)
 +        GMX_TEST_CFLAG(MSVC_SSE4_CFLAG "/arch:SSE4.1" GROMACS_C_FLAGS)
 +    endif(NOT GNU_SSE4_CFLAG)
 +    if (NOT GNU_SSE4_CFLAG AND NOT MSVC_SSE4_CFLAG)
 +        message(WARNING "No C SSE4.1 flag found. Consider a newer compiler, or disable SSE4.1 for slightly lower performance.")
 +        # Not surprising if we end up here! MSVC current does not support the SSE4.1 flag. However, it appears to accept SSE4.1
 +        # intrinsics when SSE2 support is enabled, so we try that instead.
 +        GMX_TEST_CFLAG(MSVC_SSE2_CFLAG "/arch:SSE2" GROMACS_C_FLAGS)
 +    endif(NOT GNU_SSE4_CFLAG AND NOT MSVC_SSE4_CFLAG)
 +
 +    if (CMAKE_CXX_COMPILER_LOADED)
 +        GMX_TEST_CXXFLAG(GNU_SSE4_CXXFLAG "-msse4.1" GROMACS_CXX_FLAG)
 +        if (NOT GNU_SSE4_CXXFLAG)
 +            GMX_TEST_CXXFLAG(MSVC_SSE4_CXXFLAG "/arch:SSE4.1" GROMACS_CXX_FLAGS)
 +        endif(NOT GNU_SSE4_CXXFLAG)
 +        if (NOT GNU_SSE4_CXXFLAG AND NOT MSVC_SSE4_CXXFLAG) 
 +            message(WARNING "No C++ SSE4.1 flag found. Consider a newer compiler, or disable SSE4.1 for slightly lower performance.")
 +            # Not surprising if we end up here! MSVC current does not support the SSE4.1 flag. However, it appears to accept SSE4.1
 +            # intrinsics when SSE2 support is enabled, so we try that instead.
 +            GMX_TEST_CXXFLAG(MSVC_SSE2_CXXFLAG "/arch:SSE2" GROMACS_CXX_FLAGS)
 +        endif(NOT GNU_SSE4_CXXFLAG AND NOT MSVC_SSE4_CXXFLAG)
 +    endif()
 +
 +    # This must come after we have added the -msse4.1 flag on some platforms.
 +    check_include_file(smmintrin.h  HAVE_SMMINTRIN_H ${GROMACS_C_FLAGS})
 +
 +    if(NOT HAVE_SMMINTRIN_H)
 +        message(FATAL_ERROR "Cannot find smmintrin.h, which is required for SSE4.1 intrinsics support.")
 +    endif(NOT HAVE_SMMINTRIN_H)
 +
 +    set(GMX_CPU_ACCELERATION_X86_SSE4_1 1)
 +    # The user should not be able to set this orthogonally to the acceleration
 +    set(GMX_X86_SSE4_1 1)
 +    set(GMX_X86_SSE2   1)
 +    if (NOT ACCELERATION_QUIETLY)
 +      message(STATUS "Enabling SSE4.1 Gromacs acceleration, and it will help compiler optimization.")
 +    endif()
 +
 +elseif(${GMX_CPU_ACCELERATION} STREQUAL "AVX_128_FMA" OR ${GMX_CPU_ACCELERATION} STREQUAL "AVX_256")
 +
 +    # Set the AVX compiler flag for both these choices!
 +
 +    GMX_TEST_CFLAG(GNU_AVX_CFLAG "-mavx" GROMACS_C_FLAGS)
 +    if (NOT GNU_AVX_CFLAG)
 +        GMX_TEST_CFLAG(MSVC_AVX_CFLAG "/arch:AVX" GROMACS_C_FLAGS)
 +    endif (NOT GNU_AVX_CFLAG)
 +    if (NOT GNU_AVX_CFLAG AND NOT MSVC_AVX_CFLAG)
 +        message(WARNING "No C AVX flag found. Consider a newer compiler, or try SSE4.1 (lower performance).")
 +    endif (NOT GNU_AVX_CFLAG AND NOT MSVC_AVX_CFLAG)
 +
 +    if (CMAKE_CXX_COMPILER_LOADED)
 +        GMX_TEST_CXXFLAG(GNU_AVX_CXXFLAG "-mavx" GROMACS_CXX_FLAGS)
 +        if (NOT GNU_AVX_CXXFLAG)
 +            GMX_TEST_CXXFLAG(MSVC_AVX_CXXFLAG "/arch:AVX" GROMACS_CXX_FLAGS)
 +        endif (NOT GNU_AVX_CXXFLAG)
 +        if (NOT GNU_AVX_CXXFLAG AND NOT MSVC_AVX_CXXFLAG)
 +            message(WARNING "No C++ AVX flag found. Consider a newer compiler, or try SSE4.1 (lower performance).")
 +        endif (NOT GNU_AVX_CXXFLAG AND NOT MSVC_AVX_CXXFLAG)
 +    endif()
 +
 +    # Set the FMA4 flags (MSVC doesn't require any)
 +    if(${GMX_CPU_ACCELERATION} STREQUAL "AVX_128_FMA" AND NOT MSVC)
 +        GMX_TEST_CFLAG(GNU_FMA_CFLAG "-mfma4" GROMACS_C_FLAGS)
 +        if (NOT GNU_FMA_CFLAG)
 +            message(WARNING "No C FMA4 flag found. Consider a newer compiler, or try SSE4.1 (lower performance).")
 +        endif(NOT GNU_FMA_CFLAG)
 +        if (CMAKE_CXX_COMPILER_LOADED)
 +            GMX_TEST_CXXFLAG(GNU_FMA_CXXFLAG "-mfma4" GROMACS_CXX_FLAGS)
 +            if (NOT GNU_FMA_CXXFLAG)
 +                message(WARNING "No C++ FMA flag found. Consider a newer compiler, or try SSE4.1 (lower performance).")
 +            endif (NOT GNU_FMA_CXXFLAG)
 +        endif()
 +    endif()
 +
 +    # Only test the header after we have tried to add the flag for AVX support
 +    check_include_file(immintrin.h  HAVE_IMMINTRIN_H ${GROMACS_C_FLAGS})
 +
 +    if(NOT HAVE_IMMINTRIN_H)
 +        message(FATAL_ERROR "Cannot find immintrin.h, which is required for AVX intrinsics support. Consider switching compiler.")
 +    endif(NOT HAVE_IMMINTRIN_H)
 +
 +    if(${GMX_CPU_ACCELERATION} STREQUAL "AVX_256")
 +        try_compile(TEST_AVX ${CMAKE_BINARY_DIR}
 +            "${CMAKE_SOURCE_DIR}/cmake/TestAVX.c"
 +            COMPILE_DEFINITIONS "${GROMACS_C_FLAGS}")
 +        if(NOT TEST_AVX)
 +            message(FATAL_ERROR "Cannot compile AVX intrinsics. Consider switching compiler.")
 +        endif()
 +    endif()
 +
 +    # GCC requires x86intrin.h for FMA support. MSVC 2010 requires intrin.h for FMA support.
 +    check_include_file(x86intrin.h HAVE_X86INTRIN_H ${GROMACS_C_FLAGS})
 +    check_include_file(intrin.h HAVE_INTRIN_H ${GROMACS_C_FLAGS})
 +
 +    # The user should not be able to set this orthogonally to the acceleration
 +    set(GMX_X86_SSE4_1 1)
 +    set(GMX_X86_SSE2   1)
 +
 +    # But just enable one of the choices internally...
 +    if(${GMX_CPU_ACCELERATION} STREQUAL "AVX_128_FMA")
 +        set(GMX_CPU_ACCELERATION_X86_AVX_128_FMA 1)
 +        set(GMX_X86_AVX_128_FMA 1)
 +        if (NOT ACCELERATION_QUIETLY)
 +          message(STATUS "Enabling 128-bit AVX Gromacs acceleration (with fused-multiply add), and it will help compiler optimization.")
 +        endif()
 +    else()
 +        # If we are not doing AVX_128, it must be AVX_256...
 +        set(GMX_CPU_ACCELERATION_X86_AVX_256 1)
 +        set(GMX_X86_AVX_256 1)
 +        if (NOT ACCELERATION_QUIETLY)
 +          message(STATUS "Enabling 256-bit AVX Gromacs acceleration, and it will help compiler optimization.")
 +        endif()
      endif()
  
 -#    if(HAVE_PMMINTRIN_H)
 -#        set(GMX_SSE3 1)
 -#    endif(HAVE_PMMINTRIN_H)
 -#    if(HAVE_SMMINTRIN_H)
 -#        set(GMX_SSE4_1 1)
 -#    endif(HAVE_SMMINTRIN_H)
 -
 -elseif(${GMX_ACCELERATION} STREQUAL "FORTRAN")
 -    set(GMX_FORTRAN 1)
 -    #these are switch on by default sometimes
 -    set(GMX_IA32_ASM 0)
 -    set(GMX_GMX_X86_64_ASM 0)
 -elseif(${GMX_ACCELERATION} STREQUAL "BLUEGENE")
 -# GMX_ACCELERATION=BlueGene should be set in the Toolchain-BlueGene?-???.cmake file
 -    message(STATUS "Configuring for BlueGene")
 +elseif(${GMX_CPU_ACCELERATION} STREQUAL "FORTRAN")
 +
 +#    Fortran is temporarily disabled while we push in nbNxN kernels.
 +#    We need to fake it a bit here to avoid jenkins build errors!
 +#    add_definitions(-DGMX_FORTRAN)
 +
 +elseif(${GMX_CPU_ACCELERATION} STREQUAL "BLUEGENE")
 +# GMX_CPU_ACCELERATION=BlueGene should be set in the Toolchain-BlueGene?-???.cmake file
 +    if (NOT ACCELERATION_QUIETLY)
 +      message(STATUS "Configuring for BlueGene")
 +    endif()
      set(GMX_BLUEGENE 1)
      if (${CMAKE_SYSTEM_NAME} STREQUAL "BlueGeneL")
          set(SHARED_LIBS_DEFAULT OFF CACHE BOOL "Shared libraries not compatible with BlueGene/L, disabled!" FORCE)
      set(GMX_SOFTWARE_INVSQRT OFF CACHE BOOL "Do not use software reciprocal square root on BlueGene" FORCE)
      set(GMX_POWERPC_INVSQRT ON CACHE BOOL "Use hardware reciprocal square root on BlueGene" FORCE)
      set(GMX_X11 OFF CACHE BOOL "X11 not compatible with BlueGene, disabled!" FORCE)
 -    set(GMX_THREADS OFF CACHE BOOL "Threads not compatible with BlueGene, disabled!" FORCE)
 +    set(GMX_THREAD_MPI OFF CACHE BOOL "Thread-MPI not compatible with BlueGene, disabled!" FORCE)
      set(GMX_MPI ON CACHE BOOL "Use MPI on BlueGene" FORCE)
  # Access to /etc/passwd is not available on the back end of BlueGene,
  # despite being detected by CMake. This can cause linker warnings
  # The automatic testing for endianness does not work for the BlueGene cross-compiler
      set(GMX_IEEE754_BIG_ENDIAN_BYTE_ORDER 1 CACHE INTERNAL "BlueGene has big endian FP byte order (by default)" FORCE)
      set(GMX_IEEE754_BIG_ENDIAN_WORD_ORDER 1 CACHE INTERNAL "BlueGene has big endian FP word order (by default)" FORCE)
 -elseif(${GMX_ACCELERATION} STREQUAL "POWER6")
 +elseif(${GMX_CPU_ACCELERATION} STREQUAL "POWER6")
      set(GMX_POWER6 1)
      set(GMX_SOFTWARE_INVSQRT OFF CACHE BOOL "Do not use software reciprocal square root on Power6" FORCE)
      set(GMX_POWERPC_INVSQRT ON CACHE BOOL "Use hardware reciprocal square root on Power6" FORCE)
 -elseif(${GMX_ACCELERATION} STREQUAL "IA64")
 -    set(GMX_IA64_ASM 1)
 -    set(DISABLE_WATERWATER_NLIST 1)
 -    set(DISABLE_WATER_NLIST 1)
 -elseif(${GMX_ACCELERATION} STREQUAL "ALTIVEC")
 -    check_include_files(altivec.h HAVE_ALTIVEC_H)
 -    if(HAVE_ALTIVEC_H)
 -        set(GMX_PPC_ALTIVEC 1)
 -    endif(HAVE_ALTIVEC_H)
 -else(${GMX_ACCELERATION} STREQUAL "NONE")
 -    MESSAGE(FATAL_ERROR "Unrecognized option for accelerated kernels: ${GMX_ACCELERATION}. Pick one of auto, none, SSE, Fortran, BlueGene, Power6, ia64, altivec")
 -endif(${GMX_ACCELERATION} STREQUAL "NONE")
 +else(${GMX_CPU_ACCELERATION} STREQUAL "NONE")
 +    MESSAGE(FATAL_ERROR "Unrecognized option for accelerated kernels: ${GMX_CPU_ACCELERATION}. Pick one of None, SSE2, SSE4.1, AVX_128_FMA, AVX_256, Fortran, BlueGene, Power6")
 +endif(${GMX_CPU_ACCELERATION} STREQUAL "NONE")
 +set(ACCELERATION_QUIETLY TRUE CACHE INTERNAL "")
  
  if(GMX_FORTRAN OR GMX_POWER6)
 -    if (GMX_THREADS)
 -        message(FATAL_ERROR "FORTRAN/POWER6 is incompatible with threads and only provides a speed-up on certain IBM compilers. Disable FORTRAN (or threads if you really want to use FORTRAN kernels).")
 -    endif(GMX_THREADS)
 +    if (GMX_THREAD_MPI)
 +        message(FATAL_ERROR "FORTRAN/POWER6 is incompatible with thread-MPI and only provides a speed-up on certain IBM compilers. Disable FORTRAN (or threads if you really want to use FORTRAN kernels).")
 +    endif(GMX_THREAD_MPI)
      enable_language(Fortran)
      include(FortranCInterface)
      discover_fortran_mangling(prefix isupper suffix extra_under_score found)
@@@ -931,26 -719,49 +930,26 @@@ string(TOUPPER ${GMX_FFT_LIBRARY} ${GMX
  set(PKG_FFT "")
  set(PKG_FFT_LIBS "")
  if(${GMX_FFT_LIBRARY} STREQUAL "FFTW3")
 -#    MESSAGE(STATUS "Using external FFT library - fftw3")
      if(GMX_DOUBLE)
 -        find_package(FFTW3 REQUIRED)
 -              include_directories(${FFTW3_INCLUDE_DIR})
 -        set(FFT_LIBRARIES ${FFTW3_LIBRARIES})
 -        set(PKG_FFT "fftw3")
 +        set(FFTW fftw)
      else(GMX_DOUBLE)
 -        find_package(FFTW3F REQUIRED)
 -        include_directories(${FFTW3F_INCLUDE_DIR})
 -        set(FFT_LIBRARIES ${FFTW3F_LIBRARIES})
 -        set(PKG_FFT "fftw3f")
 +        set(FFTW fftwf)
      endif(GMX_DOUBLE)
 -
 -    if(NOT FFTW3_FOUND AND NOT FFTW3F_FOUND)
 -        MESSAGE(FATAL_ERROR "Cannot find fftw3 (with correct precision). Fix it, choose another FFT library, or use the Gromacs built-in fftpack (slower)!")
 -    endif(NOT FFTW3_FOUND AND NOT FFTW3F_FOUND)
 +    find_package(FFTW COMPONENTS ${FFTW})
 +    string(TOUPPER "${FFTW}" FFTW)
 +    set(PKG_FFT "${${FFTW}_PKG}")
 +    include_directories(${${FFTW}_INCLUDE_DIRS})
 +    set(FFT_LIBRARIES ${${FFTW}_LIBRARIES})
 +    if(NOT ${FFTW}_FOUND)
 +      MESSAGE(FATAL_ERROR "Cannot find FFTW3 (with correct precision - libfftw3f for single precision GROMACS or libfftw3 for double precision GROMACS). Fix it, choose another FFT library, or use the Gromacs built-in fftpack (slower)!")
 +    endif(NOT ${FFTW}_FOUND)
  
      set(GMX_FFT_FFTW3 1)
  
 -elseif(${GMX_FFT_LIBRARY} STREQUAL "FFTW2")
 -#    MESSAGE(STATUS "Using external FFT library - fftw2")
 -    if(GMX_DOUBLE)
 -        find_package(FFTW2 REQUIRED)
 -    else(GMX_DOUBLE)
 -        find_package(FFTW2F REQUIRED)
 -    endif(GMX_DOUBLE)
 +    if (NOT ${GMX_CPU_ACCELERATION} STREQUAL "NONE" AND NOT ${FFTW}_HAVE_SIMD) 
 +      message(WARNING "The fftw library found is compiled without SIMD support, which makes it slow. Consider recompiling it or contact your admin")
 +    endif (NOT ${GMX_CPU_ACCELERATION} STREQUAL "NONE" AND NOT ${FFTW}_HAVE_SIMD) 
  
 -    if(NOT FFTW2_FOUND)
 -                 MESSAGE(FATAL_ERROR "Cannot find fftw2 (with correct precision). Fix it, choose another FFT library, or use the Gromacs built-in fftpack (slower)!")
 -    endif(NOT FFTW2_FOUND)
 -    include_directories(${FFTW2_INCLUDE_DIR})
 -    set(FFT_LIBRARIES ${FFTW2_LIBRARIES})
 -    set(PKG_FFT_LIBS ${FFTW2_LIBRARIES})
 -
 -    if("${FFTW2_LIBRARIES}" MATCHES "dfftw")
 -        set(FFTW2_NAME_DFFTW 1)
 -    elseif("${FFTW2_LIBRARIES}" MATCHES "sfftw")
 -        set(FFTW2_NAME_SFFTW 1)
 -    else("${FFTW2_LIBRARIES}" MATCHES "dfftw")
 -        set(FFTW2_NAME_FFTW 1) 
 -    endif("${FFTW2_LIBRARIES}" MATCHES "dfftw")
 -
 -    set(GMX_FFT_FFTW2 1)
  elseif(${GMX_FFT_LIBRARY} STREQUAL "MKL")
  #    MESSAGE(STATUS "Using external FFT library - Intel MKL")
      find_package(MKL REQUIRED)
@@@ -968,95 -779,40 +967,95 @@@ elseif(${GMX_FFT_LIBRARY} STREQUAL "FFT
      MESSAGE(STATUS "Using internal FFT library - fftpack")
      set(GMX_FFT_FFTPACK 1)
  else(${GMX_FFT_LIBRARY} STREQUAL "FFTW3")
 -    MESSAGE(FATAL_ERROR "Invalid FFT library setting: ${GMX_FFT_LIBRARY}. Choose one of: fftw3, fftw2, mkl, acml, fftpack")
 +    MESSAGE(FATAL_ERROR "Invalid FFT library setting: ${GMX_FFT_LIBRARY}. Choose one of: fftw3, mkl, fftpack")
  endif(${GMX_FFT_LIBRARY} STREQUAL "FFTW3")
  
 +# enable threaded fftw3 if we've found it 
 +if(FFTW3_THREADS OR FFTW3F_THREADS)
 +    add_definitions(-DFFT5D_FFTW_THREADS)
 +endif()
 +
 +set(GMX_EXTERNAL_BLAS TRUE CACHE BOOL "Use external BLAS instead of built-in")
 +set(GMX_EXTERNAL_LAPACK TRUE CACHE BOOL "Use external LAPACK instead of built-in")
  # MKL has BLAS/LAPACK routines
 -if(HAVE_MKL OR ACCELERATE_FRAMEWORK)
 -  set(GMX_EXTERNAL_BLAS TRUE CACHE BOOL "Use external BLAS instead of built-in")
 -  set(GMX_EXTERNAL_LAPACK TRUE CACHE BOOL "Use external LAPACK instead of built-in")
 -else(HAVE_MKL OR ACCELERATE_FRAMEWORK)
 -  set(GMX_EXTERNAL_BLAS FALSE CACHE BOOL "Use external BLAS instead of built-in") 
 -  set(GMX_EXTERNAL_LAPACK FALSE CACHE BOOL "Use external LAPACK instead of built-in") 
 +if(NOT HAVE_MKL AND NOT ACCELERATE_FRAMEWORK)
    if(GMX_EXTERNAL_BLAS)
 -    #FindBLAS needs Fortran
 -    enable_language(Fortran)
      if (GMX_BLAS_USER)
          list(APPEND GMX_EXTRA_LIBRARIES ${GMX_BLAS_USER})
      else(GMX_BLAS_USER)
 -        find_package(BLAS REQUIRED)
 -        list(APPEND GMX_EXTRA_LIBRARIES ${BLAS_LIBRARIES})
 +        set(BLAS_FIND_QUIETLY ON)
 +        find_package(BLAS)
 +        if (BLAS_FOUND)
 +          list(APPEND GMX_EXTRA_LIBRARIES ${BLAS_LIBRARIES})
 +        else()
 +          MESSAGE(STATUS "Using internal BLAS library")
 +          set(GMX_EXTERNAL_BLAS FALSE CACHE BOOL "Use external BLAS instead of built-in" FORCE)
 +        endif()
      endif(GMX_BLAS_USER)
    endif(GMX_EXTERNAL_BLAS)
    if(GMX_EXTERNAL_LAPACK)
 -    #FindLAPACK needs Fortran
 -    enable_language(Fortran)
 -      if (GMX_LAPACK_USER)
 +    if (GMX_LAPACK_USER)
          list(APPEND GMX_EXTRA_LIBRARIES ${GMX_LAPACK_USER})
 -      else(GMX_LAPACK_USER)
 -        find_package(LAPACK REQUIRED)
 -        list(APPEND GMX_EXTRA_LIBRARIES ${LAPACK_LIBRARIES})
 +    else(GMX_LAPACK_USER)
 +        set(LAPACK_FIND_QUIETLY ON)
 +        find_package(LAPACK)
 +        if (LAPACK_FOUND)
 +          list(APPEND GMX_EXTRA_LIBRARIES ${LAPACK_LIBRARIES})
 +        else()
 +          MESSAGE(STATUS "Using internal LAPACK library")
 +          set(GMX_EXTERNAL_LAPACK FALSE CACHE BOOL "Use external LAPACK instead of built-in" FORCE)
 +        endif()
      endif(GMX_LAPACK_USER)
    endif(GMX_EXTERNAL_LAPACK)
 -endif(HAVE_MKL OR ACCELERATE_FRAMEWORK)
 +endif()
  mark_as_advanced(GMX_EXTERNAL_LAPACK)
  mark_as_advanced(GMX_EXTERNAL_BLAS)
  
 +set(GMX_USE_PLUGINS OFF CACHE INTERNAL "Whether GROMACS will really try to compile support for VMD plugins")
 +
 +if(GMX_LOAD_PLUGINS)
 +  if(CYGWIN OR NOT WIN32)
 +    # Native Windows does not have, nor need dlopen
 +    # Note that WIN32 is set with Cygwin, but Cygwin needs dlopen to use plug-ins
 +    include(gmxTestdlopen)
 +    gmx_test_dlopen(HAVE_DLOPEN)
 +  endif()
 +
 +  # 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).")
 +    endif()
 +    if(NOT GMX_VMD_PLUGIN_PATH)
 +      find_package(VMD)
 +    endif()
 +    set(GMX_USE_PLUGINS ON)
 +    list(APPEND GMX_EXTRA_LIBRARIES ${CMAKE_DL_LIBS}) # magic cross-platform pre-set variable for dlopen library
 +    set(PKG_DL_LIBS "-l${CMAKE_DL_LIBS}")
 +  else()
 +    set(PKG_DL_LIBS)
 +  endif()
 +endif(GMX_LOAD_PLUGINS)
 +set(VMD_QUIETLY TRUE CACHE INTERNAL "")
 +
 +if(EXISTS "${CMAKE_SOURCE_DIR}/admin/.isreposource")
 +    if(NOT CMAKE_CROSSCOMPILING)
 +        option(GMX_BUILD_MANPAGES "Build man pages" ON)
 +    else()
 +        message(STATUS "Building the man pages is not available when "
 +            "cross-compiling the developer version from git")
 +    endif()
 +else()
 +    #make sure source package contains all man pages
 +    if(NOT EXISTS "${CMAKE_SOURCE_DIR}/man/man1/ngmx.1")
 +        message(FATAL_ERROR "Man pages are missing from source package.")
 +    endif()
 +endif()
 +mark_as_advanced(GMX_BUILD_MANPAGES)
 +
  # Math and thread libraries must often come after all others when linking...
  if(HAVE_LIBM)
      list(APPEND       GMX_EXTRA_LIBRARIES m)
@@@ -1075,53 -831,25 +1074,53 @@@ if (NOT DEFINED GROMACS_C_FLAGS_SET
          FORCE)
      set(CMAKE_C_FLAGS "${GROMACS_C_FLAGS} ${CMAKE_C_FLAGS}" CACHE STRING 
          "Flags used by the compiler during all build types" FORCE)
 -    set(CMAKE_CXX_FLAGS "${GROMACS_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" CACHE STRING 
 -        "Flags used by the compiler during all build types" FORCE)
 +    if (CMAKE_CXX_COMPILER_LOADED)
 +        set(CMAKE_CXX_FLAGS "${GROMACS_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" CACHE STRING 
 +            "Flags used by the compiler during all build types" FORCE)
 +    endif()
      set(CMAKE_EXE_LINKER_FLAGS 
          "${GROMACS_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" 
 -        CACHE STRING "Linker flags" FORCE) 
 +        CACHE STRING "Linker flags for creating executables" FORCE) 
 +    set(CMAKE_SHARED_LINKER_FLAGS 
 +        "${GROMACS_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" 
 +        CACHE STRING "Linker flags for creating shared libraries" FORCE) 
  endif (NOT DEFINED GROMACS_C_FLAGS_SET)
  
 +if(NOT GMX_OPENMP)
 +    #Unset all OpenMP flags in case OpenMP was disabled either by the user
 +    #or because it was only partially detected (e.g. only for C but not C++ compiler)
 +    unset(OpenMP_C_FLAGS CACHE) 
 +    unset(OpenMP_CXX_FLAGS CACHE)
 +    unset(OpenMP_LINKER_FLAGS CACHE)
 +    unset(OpenMP_SHARED_LINKER_FLAGS)
 +endif()
 +
 +######################################
 +# Output compiler and CFLAGS used
 +######################################
 +get_compiler_info(C BUILD_C_COMPILER BUILD_CFLAGS)
 +if (CMAKE_CXX_COMPILER_LOADED)
 +    get_compiler_info(CXX BUILD_CXX_COMPILER BUILD_CXXFLAGS)
 +endif ()
 +
  ########################################################################
  # Specify install locations and which subdirectories to process        #
  ########################################################################
 -if ( DEFINED GMXLIB )
 -    set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${GMXLIB}")
 +if (GMX_USE_RELATIVE_INSTALL_PATH)
 +    set(GMX_INSTALL_PREFIX "" CACHE STRING "Prefix gets appended to CMAKE_INSTALL_PREFIX. For cpack it sets the root folder of the archive.")
 +    mark_as_advanced(GMX_INSTALL_PREFIX)
  else()
 -    set(LIB_INSTALL_DIR  ${CMAKE_INSTALL_PREFIX}/lib)
 +    set(GMX_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/")
 +endif()
 +
 +if ( NOT DEFINED GMXLIB )
 +    set(GMXLIB lib)
  endif()
 -set(BIN_INSTALL_DIR  ${CMAKE_INSTALL_PREFIX}/bin)
 -set(DATA_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/gromacs)
 -set(MAN_INSTALL_DIR  ${CMAKE_INSTALL_PREFIX}/share/man)
 -set(INCL_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include)
 +set(LIB_INSTALL_DIR "${GMX_INSTALL_PREFIX}${GMXLIB}")
 +set(BIN_INSTALL_DIR  ${GMX_INSTALL_PREFIX}bin)
 +set(DATA_INSTALL_DIR ${GMX_INSTALL_PREFIX}share/gromacs)
 +set(MAN_INSTALL_DIR  ${GMX_INSTALL_PREFIX}share/man)
 +set(INCL_INSTALL_DIR ${GMX_INSTALL_PREFIX}include)
  
  set(GMXLIBDIR        ${DATA_INSTALL_DIR}/top)
  
  if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
      set(CMAKE_SKIP_BUILD_RPATH  FALSE)
      set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
 -    set(CMAKE_INSTALL_RPATH "${LIB_INSTALL_DIR}")
 +    set(CMAKE_INSTALL_RPATH "\\\$ORIGIN/../${GMXLIB}")
      set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
  endif()
  
 +#COPYING file: Only necessary for binary distributions.
 +#Simpler to always install.
 +install(FILES COPYING DESTINATION ${DATA_INSTALL_DIR} COMPONENT data)
 +
  add_subdirectory(share)
  add_subdirectory(include)
 -add_subdirectory(man)
  add_subdirectory(src)
  add_subdirectory(scripts)
  
diff --combined src/config.h.cmakein
index b532adf06a5a63967942c9221623bd5b8d5ea8af,91873e6dccb8a7f521cc7fd1183b112f3ad9ae79..40bb5d7a2cb83dc49b0dc7a22554b755c2c0057c
  #cmakedefine USE_VERSION_H
  
  /* Default location of data files */
 -#cmakedefine GMXLIBDIR "@GMXLIBDIR@"
 +#define GMXLIBDIR "@GMXLIBDIR@"
  
 -/* Hardware and OS version for build host */
 -#cmakedefine BUILD_MACHINE "@BUILD_MACHINE@"
 -
 -/* Date and time for build */
 -#cmakedefine BUILD_TIME "@BUILD_TIME@"
 -
 -/* User doing build */
 -#cmakedefine BUILD_USER "@BUILD_USER@"
 -
 -/* Turn off water-water neighborlist optimization only */
 +/* Turn off water-water neighborlist optimization only - not used right now */
  #cmakedefine DISABLE_WATERWATER_NLIST
  
 -/* Turn off all water neighborlist optimization */
 +/* Turn off all water neighborlist optimization - not used right now */
  #cmakedefine DISABLE_WATER_NLIST
  
  /* Fortran support */
  /* As F77_FUNC, but for C identifiers containing underscores. */
  #define F77_FUNC_(name,NAME)    @F77_FUNCDEF_@
  
 -/* Use the d prefix on fftw2 includes */
 -#cmakedefine FFTW2_NAME_DFFTW
 -
 -/* Dont use any prefix on fftw2 includes */
 -#cmakedefine FFTW2_NAME_FFTW
 -
 -/* Use the s prefix on fftw2 includes */
 -#cmakedefine FFTW2_NAME_SFFTW
 -
  /* IEEE754 floating-point format. Memory layout is defined by macros
   * GMX_IEEE754_BIG_ENDIAN_BYTE_ORDER and GMX_IEEE754_BIG_ENDIAN_WORD_ORDER. 
   */
  #cmakedefine GMX_FLOAT_FORMAT_IEEE754
  
 -/* Detect Cygwin */
 -#cmakedefine GMX_CYGWIN
 -
  /* Use assembly intrinsics kernels for BlueGene */
  #cmakedefine GMX_BLUEGENE
  
@@@ -64,6 -85,9 +64,6 @@@
  /* Use Built-in FFTPACK FFT library */
  #cmakedefine GMX_FFT_FFTPACK
  
 -/* Use FFTW2 FFT library */
 -#cmakedefine GMX_FFT_FFTW2
 -
  /* Use FFTW3 FFT library */
  #cmakedefine GMX_FFT_FFTW3
  
  /* Use AMD core math library */
  #cmakedefine GMX_FFT_ACML
  
 -/* Single-precision SSE instructions on ia32 */
 -#cmakedefine GMX_IA32_SSE
 +/* SSE2 instructions available */
 +#cmakedefine GMX_X86_SSE2
 +
 +/* SSE4.1 instructions available */
 +#cmakedefine GMX_X86_SSE4_1
 +
 +/* AVX 128-bit FMA instructions available */
 +#cmakedefine GMX_X86_AVX_128_FMA
  
 -/* Double-precision SSE2 instructions on ia32 */
 -#cmakedefine GMX_IA32_SSE2
 +/* AVX 256-bit instructions available */
 +#cmakedefine GMX_X86_AVX_256
  
 -/* Use ia64 assembly tuned for Itanium2 */
 -#cmakedefine GMX_IA64_ASM
 +/* SSE2 was selected as CPU acceleration level */
 +#cmakedefine GMX_CPU_ACCELERATION_X86_SSE2
 +
 +/* SSE4.1 was selected as CPU acceleration level */
 +#cmakedefine GMX_CPU_ACCELERATION_X86_SSE4_1
 +
 +/* AVX 128-bit FMA was selected as CPU acceleration level */
 +#cmakedefine GMX_CPU_ACCELERATION_X86_AVX_128_FMA
 +
 +/* AVX 256-bit was selected as CPU acceleration level */
 +#cmakedefine GMX_CPU_ACCELERATION_X86_AVX_256
 +
 +/* String for CPU acceleration choice (for writing to log files and stdout) */
 +#define GMX_CPU_ACCELERATION_STRING "@GMX_CPU_ACCELERATION@"
  
  /* Integer byte order is big endian. */
  #cmakedefine GMX_INTEGER_BIG_ENDIAN 
     (MPI or thread_mpi) */
  #cmakedefine GMX_MPI
  
 -/* Use threads for parallelization */
 -#cmakedefine GMX_THREADS
 +/* Use threads_mpi for parallelization */
 +#cmakedefine GMX_THREAD_MPI
  
 -/* Use old threading (domain decomp force calc) code */
 -#cmakedefine GMX_THREAD_SHM_FDECOMP 
 +/* Use OpenMP multithreading */
 +#cmakedefine GMX_OPENMP
  
  /* Ignore calls to nice(3) */
  #cmakedefine GMX_NO_NICE
  /* Ignore calls to system(3) */
  #cmakedefine GMX_NO_SYSTEM
  
 -/* Use PowerPC Altivec inner loops */
 -#cmakedefine GMX_PPC_ALTIVEC
 -
  /* Use (modified) Gamess-UK for QM-MM calculations */
  #cmakedefine GMX_QMMM_GAMESS
  
  /* Use the PowerPC hardware 1/sqrt(x) */
  #cmakedefine GMX_POWERPC_INVSQRT
  
 -/* Compile with dlopen */
 -#cmakedefine GMX_DLOPEN
 +/* Use sub-counters */
 +#cmakedefine GMX_CYCLE_SUBCOUNTERS
 +
 +/* Compile with plugin support */
 +#cmakedefine GMX_USE_PLUGINS
 +
 +/* Fallback path for VMD plug-ins */
 +#define GMX_VMD_PLUGIN_PATH "@GMX_VMD_PLUGIN_PATH@"
  
  /* Define when pthreads are used */
  #cmakedefine THREAD_PTHREADS
  /* Define when Windows threads are used */
  #cmakedefine THREAD_WINDOWS
  
 +/* Define when thread-MPI atomic operations are available */
 +#cmakedefine TMPI_ATOMICS
 +
  /* Define for busy wait option  */
  #cmakedefine TMPI_WAIT_FOR_NO_ONE
  
  /* Define for GetSystemInfo() */
  #cmakedefine HAVE_SYSTEM_INFO
  
 -/* Single-precision SSE instructions on X86_64 */
 -#cmakedefine GMX_X86_64_SSE
 -
 -/* Double-precision SSE2 instructions on X86_64 */
 -#cmakedefine GMX_X86_64_SSE2
 -
  /* Enable x86 gcc inline assembly */
  #cmakedefine GMX_X86_GCC_INLINE_ASM
  
 -/* Enable x86 MSVC inline assembly */
 -#cmakedefine GMX_X86_MSVC_INLINE_ASM
 -
 -/* Support for SSE intrinsics */
 -#cmakedefine GMX_SSE
 -
 -/* Support for SSE2 intrinsics */
 -#cmakedefine GMX_SSE2
 -
 -/* Support for SSE3 intrinsics */
 -#cmakedefine GMX_SSE3
 -
 -/* Support for SSE4.1 intrinsics */
 -#cmakedefine GMX_SSE4_1
 -
 -/* Define to 1 if you have the <altivec.h> header file. */
 -#cmakedefine HAVE_ALTIVEC_H
 +/* Use GPU native acceleration */
 +#cmakedefine GMX_GPU
  
  /* Define to 1 if the system has the type gmx_bool. */
  #cmakedefine HAVE_BOOL
  /* Define to 1 if you have the gsl library (-lgsl). */
  #cmakedefine HAVE_LIBGSL
  
 -/* Define to 1 if you have the xml2 library (-lxml2). */
 -#cmakedefine HAVE_LIBXML2
 -
  /* Define to 1 if you have the dl library (-ldl). */
  #cmakedefine HAVE_LIBDL
  
  /* Define to 1 if you have the _fileno() function. */
  #cmakedefine HAVE__FILENO
  
- /* Define to 1 if you have the lstat() function. */
- #cmakedefine HAVE_LSTAT
 +/* Define to 1 if you have the sigaction() function. */
 +#cmakedefine HAVE_SIGACTION
 +
 +/* Define to 1 if you have the rsqrt() function. */
 +#cmakedefine HAVE_RSQRT
 +
 +/* Define to 1 if you have the rsqrtf() function. */
 +#cmakedefine HAVE_RSQRTF
 +
 +/* Define to 1 if you have the sqrtf() function. */
 +#cmakedefine HAVE_SQRTF
 +
  /* Define to 1 if you have the <string.h> header file. */
  #cmakedefine HAVE_STRING_H
  
  /* Define to 1 if you have the <rpc/xdr.h> header file. */
  #cmakedefine HAVE_RPC_XDR_H
  
 -/* Define to 1 if yo have the <xmmintrin.h> header file. */
 -#cmakedefine HAVE_XMMINTRIN_H
 +/* Define to 1 if you have the <x86intrin.h> header file */
 +#cmakedefine HAVE_X86INTRIN_H
  
 -/* Define to 1 if yo have the <emmintrin.h> header file. */
 -#cmakedefine HAVE_EMMINTRIN_H
 +/* Define to 1 if you have the <intrin.h> header file */
 +#cmakedefine HAVE_INTRIN_H
  
 -/* Define to 1 if yo have the <pmmintrin.h> header file. */
 -#cmakedefine HAVE_PMMINTRIN_H
 -
 -/* Define to 1 if yo have the <smmintrin.h> header file. */
 -#cmakedefine HAVE_SMMINTRIN_H
 -
 -/* Define for sched.h (this is for thread_mpi)*/
 -#define HAVE_SCHED_H
 +/* Define to 1 if you have the <sched.h> header */
 +#cmakedefine HAVE_SCHED_H
  
  /* Define to 1 if you have the vprintf() function. */
  #cmakedefine HAVE_VPRINTF
  
 +/* Define to 1 if you have the sysconf() function */
 +#cmakedefine HAVE_SYSCONF
 +
 +/* Define to 1 if you have the sched_getaffinity() function */
 +#cmakedefine HAVE_SCHED_GETAFFINITY
 +
 +/* Define to 1 if you have the sched_setaffinity() function */
 +#cmakedefine HAVE_SCHED_SETAFFINITY
 +
  /* Bytes in IEEE fp word are in big-endian order if set, little-endian if not.
     Only relevant when FLOAT_FORMAT_IEEE754 is defined. */
  #cmakedefine GMX_IEEE754_BIG_ENDIAN_BYTE_ORDER
     order! Only relevant when FLOAT_FORMAT_IEEE754 is defined. */
  #cmakedefine GMX_IEEE754_BIG_ENDIAN_WORD_ORDER
  
 -/* Define as the return type of signal handlers (int or void). */
 -#cmakedefine RETSIGTYPE @RETSIGTYPE@
 -
  /* Define if SIGUSR1 is present */
  #cmakedefine HAVE_SIGUSR1
  
  #cmakedefine gid_t int
  
  /* Define to __inline__ or __inline if that is what the C compiler
 -   calls it, or to nothing if inline is not supported under any name.  */
 +   calls it, or to nothing if inline is not supported under any name.
 +   Please do NOT remove the gmx_inline keyword from here. The classical
 +   C++ inline keyword is merely a recommendation to the compiler, and
 +   many compilers support stronger alternatives (e.g. __forceinline)
 +   that we might want to use. */
 +#define gmx_inline ${INLINE_KEYWORD}
  #ifndef __cplusplus
  #define inline ${INLINE_KEYWORD}
  #endif
  
  /* Define to __restrict__ or __restrict if that is what the C compiler
 -   calls it, or to nothing if restrict is not supported under any name.  */
 -#define restrict ${RESTRICT_KEYWORD}
 +   calls it, unless we are on C99 when it is simply called restrict.
 +   Since restrict is a reserved key word in C99 we are not allowed to
 +   redefine the word itself, so call this gmx_restrict to avoid having
 +   to identify the language standard level. If it is not supported, it
 +   is still defined to an empty string here. */
 +#define gmx_restrict ${RESTRICT_KEYWORD}
  
  #ifndef CPLUSPLUS
  #ifdef __cplusplus
  #endif  
  
  /* Define to long int if <sys/types.h> does not define. */                    
 -#cmakedefine off_t int                                                                
 -                                                                                
 +#cmakedefine off_t int
 +
  /* Define to unsigned int if <sys/types.h> does not define. */
 -#cmakedefine size_t int                                                                
 +#cmakedefine size_t int
  
  /* Define to int if <sys/types.h> does not define. */
  #cmakedefine uid_t int
 -                                                                
 +
  /* Build special-purpose mdrun library */
  #cmakedefine GMX_FAHCORE   
  
diff --combined src/gmxlib/futil.c
index 3834e36b35cf3117bb8490af74168bd46d0ef91b,a88fff02b622e647e0f3c8c9c170ab8f9165c9f1..ee4d0eccfe5fe4d7100962be0dd96814be8e2c80
@@@ -36,7 -36,6 +36,7 @@@
  #ifdef HAVE_CONFIG_H
  #include <config.h>
  #endif
 +#include "gmx_header_config.h"
  
  #include <stdio.h>
  #include <stdlib.h>
@@@ -51,7 -50,7 +51,7 @@@
  #endif
  
  
 -#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
 +#ifdef GMX_NATIVE_WINDOWS
  #include <direct.h>
  #include <io.h>
  #endif
@@@ -65,7 -64,7 +65,7 @@@
  #include "statutil.h"
  
  
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
  #include "thread_mpi.h"
  #endif
  
@@@ -86,7 -85,7 +86,7 @@@ typedef struct t_pstack 
  static t_pstack *pstack=NULL;
  static gmx_bool     bUnbuffered=FALSE;
  
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
  /* this linked list is an intrinsically globally shared object, so we have
     to protect it with mutexes */
  static tMPI_Thread_mutex_t pstack_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
@@@ -101,7 -100,7 +101,7 @@@ void push_ps(FILE *fp
  {
      t_pstack *ps;
  
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
      tMPI_Thread_mutex_lock(&pstack_mutex);
  #endif
  
      ps->fp   = fp;
      ps->prev = pstack;
      pstack   = ps;
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
      tMPI_Thread_mutex_unlock(&pstack_mutex);
  #endif
  }
@@@ -150,7 -149,7 +150,7 @@@ int ffclose(FILE *fp
  #else
      t_pstack *ps,*tmp;
      int ret=0;
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
      tMPI_Thread_mutex_lock(&pstack_mutex);
  #endif
  
      else {
          while ((ps->prev != NULL) && (ps->prev->fp != fp))
              ps=ps->prev;
 -        if (ps->prev->fp == fp) {
 +        if ((ps->prev != NULL) && ps->prev->fp == fp) {
              if (ps->prev->fp != NULL)
                  ret = pclose(ps->prev->fp);
              tmp=ps->prev;
                  ret = fclose(fp);
          }
      }
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
      tMPI_Thread_mutex_unlock(&pstack_mutex);
  #endif
      return ret;
  void frewind(FILE *fp)
  {
      t_pstack *ps;
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
      tMPI_Thread_mutex_lock(&pstack_mutex);
  #endif
  
      while (ps != NULL) {
          if (ps->fp == fp) {
              fprintf(stderr,"Cannot rewind compressed file!\n");
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
              tMPI_Thread_mutex_unlock(&pstack_mutex);
  #endif
              return;
          ps=ps->prev;
      }
      rewind(fp);
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
      tMPI_Thread_mutex_unlock(&pstack_mutex);
  #endif
  }
@@@ -246,21 -245,21 +246,21 @@@ gmx_off_t gmx_ftell(FILE *stream
  gmx_bool is_pipe(FILE *fp)
  {
      t_pstack *ps;
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
      tMPI_Thread_mutex_lock(&pstack_mutex);
  #endif
  
      ps=pstack;
      while (ps != NULL) {
          if (ps->fp == fp) {
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
              tMPI_Thread_mutex_unlock(&pstack_mutex);
  #endif
              return TRUE;
          }
          ps=ps->prev;
      }
 -#ifdef GMX_THREADS
 +#ifdef GMX_THREAD_MPI
      tMPI_Thread_mutex_unlock(&pstack_mutex);
  #endif
      return FALSE;
@@@ -304,7 -303,7 +304,7 @@@ gmx_bool gmx_fexist(const char *fname
      test=fopen(fname,"r");
      if (test == NULL) {
          /*Windows doesn't allow fopen of directory - so we need to check this seperately */
 -        #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__) 
 +        #ifdef GMX_NATIVE_WINDOWS
              DWORD attr = GetFileAttributes(fname);
              return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
          #else 
@@@ -335,11 -334,7 +335,7 @@@ static gmx_bool gmx_is_file(const char 
          {
              int status;
              struct stat st_buf;
-             #ifdef HAVE_LSTAT
-                 status = lstat (fname, &st_buf);
-             #else
-                 status = stat (fname, &st_buf);
-             #endif
+             status = stat (fname, &st_buf);
              if (status != 0 || !S_ISREG(st_buf.st_mode))
              {
                  return FALSE;
@@@ -482,11 -477,6 +478,11 @@@ FILE *ffopen(const char *file,const cha
      gmx_bool bRead;
      int  bs;
  
 +    if (file == NULL) 
 +    {
 +        return NULL;
 +    }
 +
      if (mode[0]=='w') {
          make_backup(file);
      }
@@@ -540,7 -530,7 +536,7 @@@ struct gmx_director
  {
  #ifdef HAVE_DIRENT_H
      DIR  *               dirent_handle;
 -#elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
 +#elif (defined GMX_NATIVE_WINDOWS)
      intptr_t             windows_handle;
      struct _finddata_t   finddata;
      int                  first;
@@@ -571,7 -561,7 +567,7 @@@ gmx_directory_open(gmx_directory_t *p_g
          *p_gmxdir = NULL;
          rc        = EINVAL;
      }
 -#elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
 +#elif (defined GMX_NATIVE_WINDOWS)
      
      if(dirname!=NULL && strlen(dirname)>0)
      {
@@@ -666,7 -656,7 +662,7 @@@ gmx_directory_nextfile(gmx_directory_t 
          rc      = EINVAL;
      }
      
 -#elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
 +#elif (defined GMX_NATIVE_WINDOWS)
      
      if(gmxdir!=NULL)
      {
@@@ -712,7 -702,7 +708,7 @@@ gmx_directory_close(gmx_directory_t gmx
      int                     rc;
  #ifdef HAVE_DIRENT_H
      rc = (gmxdir != NULL) ? closedir(gmxdir->dirent_handle) : EINVAL;
 -#elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
 +#elif (defined GMX_NATIVE_WINDOWS)
      rc = (gmxdir != NULL) ? _findclose(gmxdir->windows_handle) : EINVAL;
  #else
      gmx_fatal(FARGS,
@@@ -770,7 -760,7 +766,7 @@@ gmx_bool search_subdirs(const char *par
   */
  static gmx_bool filename_is_absolute(char *name)
  {
 -#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
 +#ifdef GMX_NATIVE_WINDOWS
      return ((name[0] == DIR_SEPARATOR) || ((strlen(name)>3) && strncmp(name+1,":\\",2)) == 0);
  #else
      return (name[0] == DIR_SEPARATOR);
@@@ -801,7 -791,7 +797,7 @@@ gmx_bool get_libdir(char *libdir
      /* On windows & cygwin we need to add the .exe extension
       * too, or we wont be able to detect that the file exists
       */
 -#if (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64 || defined __CYGWIN__ || defined __CYGWIN32__)
 +#if (defined GMX_NATIVE_WINDOWS || defined GMX_CYGWIN)
      if(strlen(bin_name)<3 || gmx_strncasecmp(bin_name+strlen(bin_name)-4,".exe",4))
          strcat(bin_name,".exe");
  #endif
          if (!strchr(bin_name,DIR_SEPARATOR)) {
              /* No slash or backslash in name means it must be in the path - search it! */
              /* Add the local dir since it is not in the path on windows */
 -#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
 +#ifdef GMX_NATIVE_WINDOWS
              pdum=_getcwd(system_path,sizeof(system_path)-1);
  #else
              pdum=getcwd(system_path,sizeof(system_path)-1);
               * it does not start at the root, i.e.
               * name is relative to the current dir 
               */
 -#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
 +#ifdef GMX_NATIVE_WINDOWS
              pdum=_getcwd(buf,sizeof(buf)-1);
  #else
              pdum=getcwd(buf,sizeof(buf)-1);
          /* Now we should have a full path and name in full_path,
           * but on unix it might be a link, or a link to a link to a link..
           */
 -#if (!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64)
 +#ifndef GMX_NATIVE_WINDOWS
          while( (i=readlink(full_path,buf,sizeof(buf)-1)) > 0 ) {
              buf[i]='\0';
              /* If it doesn't start with "/" it is relative */
       * locations before giving up, in case we are running from e.g. 
       * a users home directory. This only works on unix or cygwin...
       */
 -#if ((!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64) || defined __CYGWIN__ || defined __CYGWIN32__)
 +#ifndef GMX_NATIVE_WINDOWS
      if(!found) 
          found=search_subdirs("/usr/local",libdir);
      if(!found) 
@@@ -999,7 -989,7 +995,7 @@@ void gmx_tmpnam(char *buf
       * since windows doesnt support it we have to separate the cases.
       * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
       */
 -#if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
 +#ifdef GMX_NATIVE_WINDOWS
      _mktemp(buf);
  #else
      fd = mkstemp(buf);
@@@ -1046,7 -1036,7 +1042,7 @@@ int gmx_truncatefile(char *path, gmx_of
  
  int gmx_file_rename(const char *oldname, const char *newname)
  {
 -#if (!(defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)))
 +#ifndef GMX_NATIVE_WINDOWS
      /* under unix, rename() is atomic (at least, it should be). */
      return rename(oldname, newname);
  #else
diff --combined src/tools/gmx_cluster.c
index 3818009b0ca04f4efb2eb53b697bedb4d2afd1c2,2abc7026bd365f376c176af5b493303c84bb5786..14a607fbd5dd970feecf227a7739e090493af7ae
  #include "viewit.h"
  #include "gmx_ana.h"
  
 -/* macro's to print to two file pointers at once (i.e. stderr and log) */
 -#define lo_ffprintf(fp1,fp2,buf) \
 -   fprintf(fp1,"%s",buf);\
 -   fprintf(fp2,"%s",buf);
 +/* print to two file pointers at once (i.e. stderr and log) */
 +static inline
 +void lo_ffprintf(FILE *fp1, FILE *fp2, const char *buf)
 +{
 +    fprintf(fp1, "%s", buf);
 +    fprintf(fp2, "%s", buf);
 +}
 +
  /* just print a prepared buffer to fp1 and fp2 */
 -#define ffprintf(fp1,fp2,buf) { lo_ffprintf(fp1,fp2,buf) }
 +static inline
 +void ffprintf(FILE *fp1, FILE *fp2, const char *buf)
 +{
 +    lo_ffprintf(fp1, fp2, buf);
 +}
 +
  /* prepare buffer with one argument, then print to fp1 and fp2 */
 -#define ffprintf1(fp1,fp2,buf,fmt,arg) {\
 -   sprintf(buf,fmt,arg);\
 -   lo_ffprintf(fp1,fp2,buf)\
 +static inline
 +void ffprintf_d(FILE *fp1, FILE *fp2, char *buf, const char *fmt, int arg)
 +{
 +    sprintf(buf, fmt, arg);
 +    lo_ffprintf(fp1, fp2, buf);
  }
 +
 +/* prepare buffer with one argument, then print to fp1 and fp2 */
 +static inline
 +void ffprintf_g(FILE *fp1, FILE *fp2, char *buf, const char *fmt, real arg)
 +{
 +    sprintf(buf, fmt, arg);
 +    lo_ffprintf(fp1, fp2, buf);
 +}
 +
 +/* prepare buffer with one argument, then print to fp1 and fp2 */
 +static inline
 +void ffprintf_s(FILE *fp1, FILE *fp2, char *buf, const char *fmt, const char *arg)
 +{
 +    sprintf(buf, fmt, arg);
 +    lo_ffprintf(fp1, fp2, buf);
 +}
 +
 +/* prepare buffer with two arguments, then print to fp1 and fp2 */
 +static inline
 +void ffprintf_dd(FILE *fp1, FILE *fp2, char *buf, const char *fmt, int arg1, int arg2)
 +{
 +    sprintf(buf, fmt, arg1, arg2);
 +    lo_ffprintf(fp1, fp2, buf);
 +}
 +
 +/* prepare buffer with two arguments, then print to fp1 and fp2 */
 +static inline
 +void ffprintf_gg(FILE *fp1, FILE *fp2, char *buf, const char *fmt, real arg1, real arg2)
 +{
 +    sprintf(buf, fmt, arg1, arg2);
 +    lo_ffprintf(fp1, fp2, buf);
 +}
 +
  /* prepare buffer with two arguments, then print to fp1 and fp2 */
 -#define ffprintf2(fp1,fp2,buf,fmt,arg1,arg2) {\
 -   sprintf(buf,fmt,arg1,arg2);\
 -   lo_ffprintf(fp1,fp2,buf)\
 +static inline
 +void ffprintf_ss(FILE *fp1, FILE *fp2, char *buf, const char *fmt, const char *arg1, const char *arg2)
 +{
 +    sprintf(buf, fmt, arg1, arg2);
 +    lo_ffprintf(fp1, fp2, buf);
  }
  
  typedef struct {
@@@ -748,7 -702,7 +748,7 @@@ static void ana_trans(t_clusters *clust
        trans[clust->cl[i-1]-1][clust->cl[i]-1]++;
        maxtrans = max(maxtrans, trans[clust->cl[i]-1][clust->cl[i-1]-1]);
      }
 -  ffprintf2(stderr,log,buf,"Counted %d transitions in total, "
 +  ffprintf_dd(stderr,log,buf,"Counted %d transitions in total, "
            "max %d between two specific clusters\n",ntranst,maxtrans);
    if (transfn) {
      fp=ffopen(transfn,"w");
@@@ -797,7 -751,7 +797,7 @@@ static void analyze_clusters(int nf, t_
    
    clear_mat(zerobox);
    
 -  ffprintf1(stderr,log,buf,"\nFound %d clusters\n\n",clust->ncl);
 +  ffprintf_d(stderr,log,buf,"\nFound %d clusters\n\n",clust->ncl);
    trxsfn=NULL;
    if (trxfn) {
      /* do we write all structures? */
        trxsfn = parse_filename(trxfn, max(write_ncl,clust->ncl));
        snew(bWrite,nf);
      }
 -    ffprintf2(stderr,log,buf,"Writing %s structure for each cluster to %s\n",
 +    ffprintf_ss(stderr,log,buf,"Writing %s structure for each cluster to %s\n",
              bAverage ? "average" : "middle", trxfn);
      if (write_ncl) {
        /* find out what we want to tell the user:
@@@ -1067,12 -1021,12 +1067,12 @@@ int gmx_cluster(int argc,char *argv[]
    const char   *fn,*trx_out_fn;
    t_clusters   clust;
    t_mat        *rms;
 -  real         *eigval;
 +  real         *eigenvalues;
    t_topology   top;
    int          ePBC;
    t_atoms      useatoms;
    t_matrix     *readmat=NULL;
 -  real         *tmp;
 +  real         *eigenvectors;
    
    int      isize=0,ifsize=0,iosize=0;
    atom_id  *index=NULL, *fitidx, *outidx;
        } else
        sprintf(buf1,"Will use P=%d, M=%d",P,M);
      }
 -    ffprintf1(stderr,log,buf,"%s for determining the neighbors\n\n",buf1);
 +    ffprintf_s(stderr,log,buf,"%s for determining the neighbors\n\n",buf1);
    } else /* method != m_jarvis */
      bUseRmsdCut = ( bBinary || method == m_linkage || method == m_gromos );
    if (bUseRmsdCut && method != m_jarvis_patrick)
    if (bReadTraj) {
      /* don't read mass-database as masses (and top) are not used */
      read_tps_conf(ftp2fn(efTPS,NFILE,fnm),buf,&top,&ePBC,&xtps,NULL,box,
-                 bAnalyze);
+                 TRUE);
      if(bPBC) {
        gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,box);
      }
      }
      fprintf(stderr,"\n\n");
    }
 -  ffprintf2(stderr,log,buf,"The RMSD ranges from %g to %g nm\n",
 +  ffprintf_gg(stderr,log,buf,"The RMSD ranges from %g to %g nm\n",
            rms->minrms,rms->maxrms);
 -  ffprintf1(stderr,log,buf,"Average RMSD is %g\n",2*rms->sumrms/(nf*(nf-1)));
 -  ffprintf1(stderr,log,buf,"Number of structures for matrix %d\n",nf);
 -  ffprintf1(stderr,log,buf,"Energy of the matrix is %g nm\n",mat_energy(rms));
 +  ffprintf_g(stderr,log,buf,"Average RMSD is %g\n",2*rms->sumrms/(nf*(nf-1)));
 +  ffprintf_d(stderr,log,buf,"Number of structures for matrix %d\n",nf);
 +  ffprintf_g(stderr,log,buf,"Energy of the matrix is %g nm\n",mat_energy(rms));
    if (bUseRmsdCut && (rmsdcut < rms->minrms || rmsdcut > rms->maxrms) )
      fprintf(stderr,"WARNING: rmsd cutoff %g is outside range of rmsd values "
            "%g to %g\n",rmsdcut,rms->minrms,rms->maxrms);
      break;
    case m_diagonalize:
      /* Do a diagonalization */
 -      snew(eigval,nf);
 -      snew(tmp,nf*nf);
 -      memcpy(tmp,rms->mat[0],nf*nf*sizeof(real));
 -      eigensolver(tmp,nf,0,nf,eigval,rms->mat[0]);
 -      sfree(tmp);
 +      snew(eigenvalues,nf);
 +      snew(eigenvectors,nf*nf);
 +      memcpy(eigenvectors,rms->mat[0],nf*nf*sizeof(real));
 +      eigensolver(eigenvectors,nf,0,nf,eigenvalues,rms->mat[0]);
 +      sfree(eigenvectors);
        
        fp = xvgropen(opt2fn("-ev",NFILE,fnm),"RMSD matrix Eigenvalues",
                      "Eigenvector index","Eigenvalues (nm\\S2\\N)",oenv);
        for(i=0; (i<nf); i++)
 -          fprintf(fp,"%10d  %10g\n",i,eigval[i]);
 +          fprintf(fp,"%10d  %10g\n",i,eigenvalues[i]);
            ffclose(fp);
        break;
    case m_monte_carlo:
diff --combined src/tools/gmx_hbond.c
index cdf790cbf50fd948c3fee892bf212d6f1d34b6bf,f851d545029d2426d8e38044305f3c0928e737fc..ea53b9d95c95e2872b6d81c2999a043aee09c46b
  #include <math.h>
  
  /*#define HAVE_NN_LOOPS*/
 -/* Set environment variable CFLAGS = "-fopenmp" when running
 - * configure and define DOUSEOPENMP to make use of parallelized
 - * calculation of autocorrelation function.
 - * It also adds a new option -nthreads which sets the number of threads.
 - * */
 -/*#define DOUSEOPENMP*/
 -
 -#ifdef DOUSEOPENMP
 -#define HAVE_OPENMP
 -#include "omp.h"
 -#endif
 +
 +#include "gmx_omp.h"
  
  #include "statutil.h"
  #include "copyrite.h"
@@@ -72,7 -81,7 +72,7 @@@ const char *hxtypenames[NRHXTYPES]
  {"n-n","n-n+1","n-n+2","n-n+3","n-n+4","n-n+5","n-n>6"};
  #define MAXHH 4
  
 -#ifdef HAVE_OPENMP
 +#ifdef GMX_OPENMP
  #define MASTER_THREAD_ONLY(threadNr) ((threadNr)==0)
  #else
  #define MASTER_THREAD_ONLY(threadNr) ((threadNr)==(threadNr))
@@@ -282,7 -291,10 +282,7 @@@ static PSTYPE periodicIndex(ivec r, t_g
      /* Not found apparently. Add it to the list! */
      /* printf("New shift found: %i,%i,%i\n",r[XX],r[YY],r[ZZ]); */
  
 -/* Unfortunately this needs to be critical it seems. */
 -#ifdef HAVE_OPENMP
  #pragma omp critical
 -#endif
      {
          if (!per->p2i) {
              fprintf(stderr, "p2i not initialized. This shouldn't happen!\n");
@@@ -555,8 -567,9 +555,8 @@@ static void storeHbEnergy(t_hbdata *hb
          E = 0;
  
      hb->hbE.E[d][a][h][frame] = E;
 -#ifdef HAVE_OPENMP
 +
  #pragma omp critical
 -#endif
      {
          hb->hbE.Etot[frame] += E;
      }
@@@ -716,7 -729,6 +716,7 @@@ static void add_ff(t_hbdata *hbd,int id
        
          }
      }
 +
  }
  
  static void inc_nhbonds(t_donors *ddd,int d, int h)
@@@ -837,16 -849,12 +837,16 @@@ static void add_hbond(t_hbdata *hb,int 
              k = 0;
      
          if (hb->bHBmap) {
 -            if (hb->hbmap[id][ia] == NULL) {
 -                snew(hb->hbmap[id][ia],1);
 -                snew(hb->hbmap[id][ia]->h,hb->maxhydro);
 -                snew(hb->hbmap[id][ia]->g,hb->maxhydro);
 +
 +#pragma omp critical
 +            {
 +                if (hb->hbmap[id][ia] == NULL) {
 +                    snew(hb->hbmap[id][ia],1);
 +                    snew(hb->hbmap[id][ia]->h,hb->maxhydro);
 +                    snew(hb->hbmap[id][ia]->g,hb->maxhydro);
 +                }
 +                add_ff(hb,id,k,ia,frame,ihb,p);
              }
 -            add_ff(hb,id,k,ia,frame,ihb,p);
          }
      
          /* Strange construction with frame >=0 is a relic from old code
          inc_nhbonds(&(hb->d),d,h);
  }
  
 -/* Now a redundant function. It might find use at some point though. */
 -static gmx_bool in_list(atom_id selection,int isize,atom_id *index)
 -{
 -    int i;
 -    gmx_bool bFound;
 -  
 -    bFound=FALSE;
 -    for(i=0; (i<isize) && !bFound; i++)
 -        if(selection == index[i])
 -            bFound=TRUE;
 -  
 -    return bFound;
 -}
 -
  static char *mkatomname(t_atoms *atoms,int i)
  {
      static char buf[32];
@@@ -1018,7 -1040,7 +1018,7 @@@ static void search_donors(t_topology *t
      int        i,j,nra,n;
      t_functype func_type;
      t_ilist    *interaction;
 -    atom_id    nr1,nr2;
 +    atom_id    nr1,nr2,nr3;
      gmx_bool       stop;
  
      if (!ddd->dptr) {
        
                  /* check out this functype */
                  if (func_type == F_SETTLE) {
 -                    nr1=interaction->iatoms[i+1];
 +                    nr1 = interaction->iatoms[i+1];
 +                    nr2 = interaction->iatoms[i+2];
 +                    nr3 = interaction->iatoms[i+3];
          
                      if (ISINGRP(datable[nr1])) {
 -                        if (ISINGRP(datable[nr1+1])) {
 +                        if (ISINGRP(datable[nr2])) {
                              datable[nr1] |= DON;
                              add_dh(ddd,nr1,nr1+1,grp,datable);
                          }
 -                        if (ISINGRP(datable[nr1+2])) {
 +                        if (ISINGRP(datable[nr3])) {
                              datable[nr1] |= DON;
                              add_dh(ddd,nr1,nr1+2,grp,datable);
                          }
@@@ -1140,6 -1160,21 +1140,6 @@@ static t_gridcell ***init_grid(gmx_boo
      return grid;
  }
  
 -static void control_pHist(t_hbdata *hb, int nframes)
 -{
 -    int i,j,k;
 -    PSTYPE p;
 -    for (i=0;i<hb->d.nrd;i++)
 -        for (j=0;j<hb->a.nra;j++)
 -            if (hb->per->pHist[i][j].len != 0)
 -                for (k=hb->hbmap[i][j][0].n0; k<nframes; k++) {
 -                    p = getPshift(hb->per->pHist[i][j], k);
 -                    if (p>hb->per->nper)
 -                        fprintf(stderr, "Weird stuff in pHist[%i][%i].p at frame %i: p=%i\n",
 -                                i,j,k,p);
 -                }
 -}
 -
  static void reset_nhbonds(t_donors *ddd)
  {
      int i,j;
@@@ -1325,18 -1360,23 +1325,18 @@@ static void count_da_grid(ivec ngrid, t
   * This could be implemented slightly more efficient, but the code
   * would get much more complicated.
   */
 -#define B(n,x,bTric,bEdge) ((n==1) ? x : bTric&&(bEdge) ? 0   : (x-1))
 -#define E(n,x,bTric,bEdge) ((n==1) ? x : bTric&&(bEdge) ? n-1 : (x+1))
 -#define GRIDMOD(j,n) (j+n)%(n)
 -#define LOOPGRIDINNER(x,y,z,xx,yy,zz,xo,yo,zo,n,bTric)                  \
 -    for(zz=B(n[ZZ],zo,bTric,FALSE); zz<=E(n[ZZ],zo,bTric,FALSE); zz++) { \
 -    z=GRIDMOD(zz,n[ZZ]);                                                \
 -    for(yy=B(n[YY],yo,bTric,z==0||z==n[ZZ]-1);                          \
 -        yy<=E(n[YY],yo,bTric,z==0||z==n[ZZ]-1); yy++) {                 \
 -    y=GRIDMOD(yy,n[YY]);                                                \
 -    for(xx=B(n[XX],xo,bTric,y==0||y==n[YY]-1||z==0||z==n[ZZ]-1);              \
 -        xx<=E(n[XX],xo,bTric,y==0||y==n[YY]-1||z==0||z==n[ZZ]-1); xx++) { \
 -    x=GRIDMOD(xx,n[XX]);
 -#define ENDLOOPGRIDINNER                                                \
 -    }                                                                   \
 -        }                                                               \
 -                                        }                                                             \
 -                                                                        \
 +static inline gmx_bool grid_loop_begin(int n, int x, gmx_bool bTric, gmx_bool bEdge)
 +{
 +    return ((n==1) ? x : bTric && bEdge ? 0     : (x-1));
 +}
 +static inline gmx_bool grid_loop_end(int n, int x, gmx_bool bTric, gmx_bool bEdge)
 +{
 +    return ((n==1) ? x : bTric && bEdge ? (n-1) : (x+1));
 +}
 +static inline int grid_mod(int j, int n)
 +{
 +    return (j+n) % (n);
 +}
  
  static void dump_grid(FILE *fp, ivec ngrid, t_gridcell ***grid)
  {
@@@ -1392,6 -1432,17 +1392,6 @@@ static void free_grid(ivec ngrid, t_gri
      g=NULL;
  }
  
 -static void pbc_correct(rvec dx,matrix box,rvec hbox)
 -{
 -    int m;
 -    for(m=DIM-1; m>=0; m--) {
 -        if ( dx[m] < -hbox[m] )
 -            rvec_inc(dx,box[m]);
 -        else if ( dx[m] >= hbox[m] )
 -            rvec_dec(dx,box[m]);
 -    }
 -}
 -
  void pbc_correct_gem(rvec dx,matrix box,rvec hbox)
  {
      int m;
@@@ -1499,7 -1550,10 +1499,7 @@@ static int is_hbond(t_hbdata *hb,int gr
          if (bDA || (!bDA && (rha2 <= rc2))) {
              rvec_sub(x[d],x[hh],r_dh);
              if (bBox) {
 -                if (hb->bGem)
 -                    pbc_correct_gem(r_dh,box,hbox);
 -                else
 -                    pbc_correct_gem(r_dh,box,hbox);
 +                pbc_correct_gem(r_dh,box,hbox);
              }
        
              if (!bDA)
@@@ -2228,14 -2282,14 +2228,14 @@@ static void do_hbac(const char *fn,t_hb
                                  "Ac(t)",
                                  "Cc\\scontact,hb\\v{}\\z{}(t)",
                                  "-dAc\\sfs\\v{}\\z{}/dt" };
 -    gmx_bool bNorm=FALSE;
 +    gmx_bool bNorm=FALSE, bOMP=FALSE;
      double nhb = 0;
      int nhbi=0;
      real *rhbex=NULL,*ht,*gt,*ght,*dght,*kt;
      real *ct,*p_ct,tail,tail2,dtail,ct_fac,ght_fac,*cct;
      const real tol = 1e-3;
      int   nframes = hb->nframes,nf;
 -    unsigned int **h,**g;
 +    unsigned int **h=NULL,**g=NULL;
      int   nh,nhbonds,nhydro,ngh;
      t_hbond *hbh;
      PSTYPE p, *pfound = NULL, np;
      t_E *E;
      double *ctdouble, *timedouble, *fittedct;
      double fittolerance=0.1;
 +    int *dondata=NULL, thisThread;
  
      enum {AC_NONE, AC_NN, AC_GEM, AC_LUZAR};
  
 -
 -#ifdef HAVE_OPENMP
 -    int *dondata=NULL, thisThread;
 +#ifdef GMX_OPENMP
 +    bOMP = TRUE;
 +#else
 +    bOMP = FALSE;
  #endif
  
 -
      printf("Doing autocorrelation ");
  
      /* Decide what kind of ACF calculations to do. */
          if (bGemFit)
              sprintf(legGem[(bBallistic ? 3:2)], "Ac\\s%s,fit\\v{}\\z{}(t)", gemType);
  
 -    } else {
 +    }
 +    else
 +    {
          acType = AC_LUZAR;
          printf("according to the theory of Luzar and Chandler.\n");
      }
    
      nn = nframes/2;
    
 -    if (acType != AC_NN ||
 -#ifndef HAVE_OPENMP
 -        TRUE
 -#else
 -        FALSE
 -#endif
 -        ) {
 +    if (acType != AC_NN || bOMP) {
          snew(h,hb->maxhydro);
          snew(g,hb->maxhydro);
      }
      ngh     = 0;
      anhb    = 0;
  
 -    /* ------------------------------------------------
 -     * I got tired of waiting for the acf calculations
 -     * and parallelized it with openMP
 -     * set environment variable CFLAGS = "-fopenmp" when running
 -     * configure and define DOUSEOPENMP to make use of it.
 -     */
 -
 -#ifdef HAVE_OPENMP  /* ================================================= \
 -                     * Set up the OpenMP stuff,                           |
 -                     * like the number of threads and such                |
 -                     */
 -    if (acType != AC_LUZAR)
 +    if (acType != AC_LUZAR && bOMP)
      {
 -/* #if (_OPENMP >= 200805) /\* =====================\ *\/ */
 -/*         nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_thread_limit()); */
 -/* #else */
 -        nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_num_procs());
 -/* #endif /\* _OPENMP >= 200805 ====================/ *\/ */
 +        nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, gmx_omp_get_max_threads());
  
 -        omp_set_num_threads(nThreads);
 +        gmx_omp_set_num_threads(nThreads);
          snew(dondata, nThreads);
          for (i=0; i<nThreads; i++)
              dondata[i] = -1;
                  fprintf(stderr, "%-7s", tmpstr);
              }
          }
 -        fprintf(stderr, "\n"); /*                                         | */
 -    }  /*                                                                 | */
 -#endif /* HAVE_OPENMP ===================================================/  */
 +        fprintf(stderr, "\n");
 +    }
  
  
      /* Build the ACF according to acType */
  #ifdef HAVE_NN_LOOPS
          /* Here we're using the estimated energy for the hydrogen bonds. */
          snew(ct,nn);
 -#ifdef HAVE_OPENMP /* ==================================\ */      
 +
  #pragma omp parallel                            \
 -    private(i, j, k, nh, E, rhbex, thisThread),       \
 +    private(i, j, k, nh, E, rhbex, thisThread)  \
      default(shared)
          {
  #pragma omp barrier
 -            thisThread = omp_get_thread_num();
 +            thisThread = gmx_omp_get_thread_num();
              rhbex = NULL;
 -#endif /* ==============================================/ */
  
              snew(rhbex, n2);
              memset(rhbex, 0, n2*sizeof(real)); /* Trust no-one, not even malloc()! */
  
 -#ifdef HAVE_OPENMP /* ################################################## \
 -                    *                                                    #
 -                    *                                                    #
 -                    */
  #pragma omp barrier
  #pragma omp for schedule (dynamic)
 -#endif
              for (i=0; i<hb->d.nrd; i++) /* loop over donors */
              {
 -#ifdef HAVE_OPENMP /* ====== Write some output ======\ */
 +                if (bOMP)
 +                {
  #pragma omp critical
 +                    {
 +                        dondata[thisThread] = i;
 +                        parallel_print(dondata, nThreads);
 +                    }
 +                }
 +                else
                  {
 -                    dondata[thisThread] = i;
 -                    parallel_print(dondata, nThreads);
 +                    fprintf(stderr, "\r %i", i);
                  }
 -#else
 -                fprintf(stderr, "\r %i", i);
 -#endif /* ===========================================/ */
  
                  for (j=0; j<hb->a.nra; j++) /* loop over acceptors */
                  {
                      
                              low_do_autocorr(NULL,oenv,NULL,nframes,1,-1,&(rhbex),hb->time[1]-hb->time[0],
                                              eacNormal,1,FALSE,bNorm,FALSE,0,-1,0,1);
 -#ifdef HAVE_OPENMP
  #pragma omp critical
 -#endif
                              {
                                  for(k=0; (k<nn); k++)
                                      ct[k] += rhbex[k];
              }           /* i loop */
              sfree(rhbex);
  #pragma omp barrier
 -#ifdef HAVE_OPENMP 
 -            /*                                                           # */
 -        } /* End of parallel block                                       # */
 -        /* ##############################################################/ */
 -        sfree(dondata);
 -#endif
 +        }
 +
 +        if (bOMP)
 +        {
 +            sfree(dondata);
 +        }
          normalizeACF(ct, NULL, 0, nn);
          snew(ctdouble, nn);
          snew(timedouble, nn);
                      hb->time[j]-hb->time[0],
                      ct[j],
                      ctdouble[j]);
 -        fclose(fp);
 +        xvgrclose(fp);
          sfree(ct);
          sfree(ctdouble);
          sfree(timedouble);
      case AC_GEM:
          snew(ct,2*n2);
          memset(ct,0,2*n2*sizeof(real));
 -#ifndef HAVE_OPENMP
 +#ifndef GMX_OPENMP
          fprintf(stderr, "Donor:\n");
  #define __ACDATA ct
  #else
  #define __ACDATA p_ct
  #endif
  
 -#ifdef HAVE_OPENMP /*  =========================================\
 -                    *                                          */
 -#pragma omp parallel default(none)                              \
 +#pragma omp parallel                                            \
      private(i, k, nh, hbh, pHist, h, g, n0, nf, np, j, m,             \
              pfound, poff, rHbExGem, p, ihb, mMax,               \
              thisThread, p_ct)                                   \
 -    shared(hb, dondata, ct, nn, nThreads, n2, stderr, bNorm,    \
 -           nframes, bMerge, bContact)
 +    default(shared)
          { /* ##########  THE START OF THE ENORMOUS PARALLELIZED BLOCK!  ########## */
              h = NULL;
              g = NULL;
 -            thisThread = omp_get_thread_num();
 +            thisThread = gmx_omp_get_thread_num();
              snew(h,hb->maxhydro);
              snew(g,hb->maxhydro);
              mMax = INT_MIN;
              /* I'm using a chunk size of 1, since I expect      \
               * the overhead to be really small compared         \
               * to the actual calculations                       \ */
 -#pragma omp for schedule(dynamic,1) nowait /*                   \ */
 -#endif /* HAVE_OPENMP  =========================================/ */
 -      
 +#pragma omp for schedule(dynamic,1) nowait
              for (i=0; i<hb->d.nrd; i++) {
 -#ifdef HAVE_OPENMP
 +
 +                if (bOMP)
 +                {
  #pragma omp critical
 +                    {
 +                        dondata[thisThread] = i;
 +                        parallel_print(dondata, nThreads);
 +                    }
 +                }
 +                else
                  {
 -                    dondata[thisThread] = i;
 -                    parallel_print(dondata, nThreads);
 +                    fprintf(stderr, "\r %i", i);
                  }
 -#else
 -                fprintf(stderr, "\r %i", i);
 -#endif
 -      
                  for (k=0; k<hb->a.nra; k++) {
                      for (nh=0; nh < ((bMerge || bContact) ? 1 : hb->d.nhydro[i]); nh++) {
                          hbh = hb->hbmap[i][k];
                              pHist = &(hb->per->pHist[i][k]);
                              if (ISHB(hbh->history[nh]) && pHist->len != 0) {
  
 -/* No need for a critical section */
 -/* #ifdef HAVE_OPENMP */
 -/* #pragma omp critical */
 -/* #endif */
                                  {
                                      h[nh] = hbh->h[nh];
                                      g[nh] = hb->per->gemtype==gemAD ? hbh->g[nh] : NULL;
                                                  srenew(poff,np);
                                              }
  
 -/* This shouldn't have to be critical, right? */
 -/* #ifdef HAVE_OPENMP */
 -/* #pragma omp critical */
 -/* #endif */
                                              {
                                                  if (rHbExGem != NULL && rHbExGem[m] != NULL) {
                                                      /* This must be done, as this array was most likey
  
              sfree(h);
              sfree(g);
 -#ifdef HAVE_OPENMP /* =======================================\ */
 -#pragma omp critical
 +
 +            if (bOMP)
              {
 -                for (i=0; i<nn; i++)
 -                    ct[i] += p_ct[i];
 +#pragma omp critical
 +                {
 +                    for (i=0; i<nn; i++)
 +                        ct[i] += p_ct[i];
 +                }
 +                sfree(p_ct);
              }
 -            sfree(p_ct);
  
          } /* ########## THE END OF THE ENORMOUS PARALLELIZED BLOCK ########## */
 -        sfree(dondata);
 -#endif /* HAVE_OPENMP =======================================/ */
 +        if (bOMP)
 +        {
 +            sfree(dondata);
 +        }
  
          normalizeACF(ct, NULL, 0, nn);
  
                  fprintf(fp,"  %10g", fittedct[j]);
              fprintf(fp,"\n");
          }
 -        fclose(fp);
 +        xvgrclose(fp);
  
          sfree(ctdouble);
          sfree(timedouble);
@@@ -2895,7 -2978,10 +2895,7 @@@ static void dump_hbmap(t_hbdata *hb
      fp = opt2FILE("-hbn",nfile,fnm,"w");
      if (opt2bSet("-g",nfile,fnm)) {
          fplog = ffopen(opt2fn("-g",nfile,fnm),"w");
 -        if (bContact)
 -            fprintf(fplog,"# %10s  %12s  %12s\n","Donor","Hydrogen","Acceptor");
 -        else
 -            fprintf(fplog,"# %10s  %12s  %12s\n","Donor","Hydrogen","Acceptor");
 +        fprintf(fplog,"# %10s  %12s  %12s\n","Donor","Hydrogen","Acceptor");
      }
      else
          fplog = NULL;
          ffclose(fplog);
  }
  
 -#ifdef HAVE_OPENMP
  /* sync_hbdata() updates the parallel t_hbdata p_hb using hb as template.
   * It mimics add_frames() and init_frame() to some extent. */
  static void sync_hbdata(t_hbdata *hb, t_hbdata *p_hb,
       * even though the data its members point to will change,
       * hence no need for re-syncing. */
  }
 -#endif
  
  int gmx_hbond(int argc,char *argv[])
  {
          "which should contain exactly one atom. In this case, only hydrogen",
          "bonds between atoms within the shell distance from the one atom are",
          "considered.[PAR]",
 +
 +        "With option -ac, rate constants for hydrogen bonding can be derived with the model of Luzar and Chandler",
 +        "(Nature 394, 1996; J. Chem. Phys. 113:23, 2000) or that of Markovitz and Agmon (J. Chem. Phys 129, 2008).",
 +        "If contact kinetics are analyzed by using the -contact option, then",
 +        "n(t) can be defined as either all pairs that are not within contact distance r at time t",
 +        "(corresponding to leaving the -r2 option at the default value 0) or all pairs that",
 +        "are within distance r2 (corresponding to setting a second cut-off value with option -r2).",
 +        "See mentioned literature for more details and definitions."
 +        "[PAR]",
      
          /*    "It is also possible to analyse specific hydrogen bonds with",
                "[TT]-sel[tt]. This index file must contain a group of atom triplets",
            "Use reversible geminate recombination for the kinetics/thermodynamics calclations. See Markovitch et al., J. Chem. Phys 129, 084505 (2008) for details."},
          { "-diff", FALSE, etREAL, {&D},
            "Dffusion coefficient to use in the reversible geminate recombination kinetic model. If negative, then it will be fitted to the ACF along with ka and kd."},
 -#ifdef HAVE_OPENMP
 +#ifdef GMX_OPENMP
          { "-nthreads", FALSE, etINT, {&nThreads},
            "Number of threads used for the parallel loop over autocorrelations. nThreads <= 0 means maximum number of threads. Requires linking with OpenMP. The number of threads is limited by the number of processors (before OpenMP v.3 ) or environment variable OMP_THREAD_LIMIT (OpenMP v.3)"},
  #endif
      matrix  box;
      real    t,ccut,dist=0.0,ang=0.0;
      double  max_nhb,aver_nhb,aver_dist;
 -    int     h=0,i,j,k=0,l,start,end,id,ja,ogrp,nsel;
 +    int     h=0,i=0,j,k=0,l,start,end,id,ja,ogrp,nsel;
      int     xi,yi,zi,ai;
      int     xj,yj,zj,aj,xjj,yjj,zjj;
      int     xk,yk,zk,ak,xkk,ykk,zkk;
      gmx_bool    bSelected,bHBmap,bStop,bTwo,was,bBox,bTric;
 -    int     *adist,*rdist;
 +    int     *adist,*rdist,*aptr,*rprt;
      int        grp,nabin,nrbin,bin,resdist,ihb;
      char       **leg;
 -    t_hbdata   *hb;
 +    t_hbdata   *hb,*hbptr;
      FILE       *fp,*fpins=NULL,*fpnhb=NULL;
      t_gridcell ***grid;
      t_ncell    *icell,*jcell,*kcell;
      int     threadNr=0;
      gmx_bool    bGem, bNN, bParallel;
      t_gemParams *params=NULL;
 +    gmx_bool    bEdge_yjj, bEdge_xjj, bOMP;
      
 -    CopyRight(stdout,argv[0]);
 +    t_hbdata **p_hb=NULL;               /* one per thread, then merge after the frame loop */
 +    int **p_adist=NULL, **p_rdist=NULL; /* a histogram for each thread. */
 +
 +#ifdef GMX_OPENMP
 +    bOMP = TRUE;
 +#else
 +    bOMP = FALSE;
 +#endif
 +
 +    CopyRight(stderr,argv[0]);
  
      npargs = asize(pa);  
      ppa    = add_acf_pargs(&npargs,pa);
              gmx_fatal(FARGS,"Can not analyze contact between H and A: turn off -noda");
          }
      }
 -
 -#ifndef HAVE_LIBGSL
 -    /* Don't pollute stdout with information about external libraries.
 -     *
 -     * printf("NO GSL! Can't find and take away ballistic term in ACF without GSL\n.");
 -     */
 -#endif
    
      /* Initiate main data structure! */
      bHBmap = (opt2bSet("-ac",NFILE,fnm) ||
                opt2bSet("-hbm",NFILE,fnm) ||
                bGem);
    
 -#ifdef HAVE_OPENMP
 -    /* Same thing here. There is no reason whatsoever to write the specific version of
 -     * OpenMP used for compilation to stdout for normal usage.
 -     *
 -     * printf("Compiled with OpenMP (%i)\n", _OPENMP);
 -     */
 -#endif
 -
 -    /*   if (bContact && bGem) */
 -    /*     gmx_fatal(FARGS, "Can't do reversible geminate recombination with -contact yet."); */
 -
      if (opt2bSet("-nhbdist",NFILE,fnm)) {
          const char *leg[MAXHH+1] = { "0 HBs", "1 HB", "2 HBs", "3 HBs", "Total" };
          fpnhb = xvgropen(opt2fn("-nhbdist",NFILE,fnm),
  
      bParallel = FALSE;
  
 -#ifndef HAVE_OPENMP
 +#ifndef GMX_OPENMP
  #define __ADIST adist
  #define __RDIST rdist
  #define __HBDATA hb
 -#else /* HAVE_OPENMP ==================================================       \
 +#else /* GMX_OPENMP ==================================================        \
         * Set up the OpenMP stuff,                                       |
         * like the number of threads and such                            |
         * Also start the parallel loop.                                  |
  #define __ADIST p_adist[threadNr]
  #define __RDIST p_rdist[threadNr]
  #define __HBDATA p_hb[threadNr]
 +#endif
 +    if (bOMP)
 +    {
 +        bParallel = !bSelected;
  
 -    bParallel = !bSelected;
 +        if (bParallel)
 +        {
 +            actual_nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, gmx_omp_get_max_threads());
  
 -    if (bParallel)
 -    {
 -/* #if (_OPENMP > 200805) */
 -/*         actual_nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_thread_limit()); */
 -/* #else */
 -        actual_nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_num_procs());
 -/* #endif */
 -        omp_set_num_threads(actual_nThreads);
 -        printf("Frame loop parallelized with OpenMP using %i threads.\n", actual_nThreads);
 -        fflush(stdout);
 -    }
 -    else
 -    {
 -        actual_nThreads = 1;
 -    }
 +            gmx_omp_set_num_threads(actual_nThreads);
 +            printf("Frame loop parallelized with OpenMP using %i threads.\n", actual_nThreads);
 +            fflush(stdout);
 +        }
 +        else
 +        {
 +            actual_nThreads = 1;
 +        }
  
 -    t_hbdata **p_hb;          /* one per thread, then merge after the frame loop */
 -    int **p_adist, **p_rdist; /* a histogram for each thread. */
 -    snew(p_hb,    actual_nThreads);
 -    snew(p_adist, actual_nThreads);
 -    snew(p_rdist, actual_nThreads);
 -    for (i=0; i<actual_nThreads; i++)
 -    {
 -        snew(p_hb[i], 1);
 -        snew(p_adist[i], nabin+1);
 -        snew(p_rdist[i], nrbin+1);
 -
 -        p_hb[i]->max_frames = 0;
 -        p_hb[i]->nhb = NULL;
 -        p_hb[i]->ndist = NULL;
 -        p_hb[i]->n_bound = NULL;
 -        p_hb[i]->time = NULL;
 -        p_hb[i]->nhx = NULL;
 -
 -        p_hb[i]->bHBmap     = hb->bHBmap;
 -        p_hb[i]->bDAnr      = hb->bDAnr;
 -        p_hb[i]->bGem       = hb->bGem;
 -        p_hb[i]->wordlen    = hb->wordlen;
 -        p_hb[i]->nframes    = hb->nframes;
 -        p_hb[i]->maxhydro   = hb->maxhydro;
 -        p_hb[i]->danr       = hb->danr;
 -        p_hb[i]->d          = hb->d;
 -        p_hb[i]->a          = hb->a;
 -        p_hb[i]->hbmap      = hb->hbmap;
 -        p_hb[i]->time       = hb->time; /* This may need re-syncing at every frame. */
 -        p_hb[i]->per        = hb->per;
 +        snew(p_hb,    actual_nThreads);
 +        snew(p_adist, actual_nThreads);
 +        snew(p_rdist, actual_nThreads);
 +        for (i=0; i<actual_nThreads; i++)
 +        {
 +            snew(p_hb[i], 1);
 +            snew(p_adist[i], nabin+1);
 +            snew(p_rdist[i], nrbin+1);
 +
 +            p_hb[i]->max_frames = 0;
 +            p_hb[i]->nhb = NULL;
 +            p_hb[i]->ndist = NULL;
 +            p_hb[i]->n_bound = NULL;
 +            p_hb[i]->time = NULL;
 +            p_hb[i]->nhx = NULL;
 +
 +            p_hb[i]->bHBmap     = hb->bHBmap;
 +            p_hb[i]->bDAnr      = hb->bDAnr;
 +            p_hb[i]->bGem       = hb->bGem;
 +            p_hb[i]->wordlen    = hb->wordlen;
 +            p_hb[i]->nframes    = hb->nframes;
 +            p_hb[i]->maxhydro   = hb->maxhydro;
 +            p_hb[i]->danr       = hb->danr;
 +            p_hb[i]->d          = hb->d;
 +            p_hb[i]->a          = hb->a;
 +            p_hb[i]->hbmap      = hb->hbmap;
 +            p_hb[i]->time       = hb->time; /* This may need re-syncing at every frame. */
 +            p_hb[i]->per        = hb->per;
  
  #ifdef HAVE_NN_LOOPS
 -        p_hb[i]->hbE = hb->hbE;
 +            p_hb[i]->hbE = hb->hbE;
  #endif
  
 -        p_hb[i]->nrhb   = 0;
 -        p_hb[i]->nrdist = 0;
 +            p_hb[i]->nrhb   = 0;
 +            p_hb[i]->nrdist = 0;
 +        }
      }
    
      /* Make a thread pool here,
       * instead of forking anew at every frame. */
    
  #pragma omp parallel                                    \
 -    private(i, j, h, ii, jj, hh, E,                     \
 +    firstprivate(i)                                     \
 +    private(j, h, ii, jj, hh, E,                        \
              xi, yi, zi, xj, yj, zj, threadNr,           \
              dist, ang, peri, icell, jcell,              \
              grp, ogrp, ai, aj, xjj, yjj, zjj,           \
              xk, yk, zk, ihb, id,  resdist,              \
 -            xkk, ykk, zkk, kcell, ak, k, bTric)        \
 -    default(none)                                       \
 -    shared(hb, p_hb, p_adist, p_rdist, actual_nThreads, \
 -           x, bBox, box, hbox, rcut, r2cut, rshell,     \
 -           shatom, ngrid, grid, nframes, t,             \
 -           bParallel, bNN, index, bMerge, bContact,     \
 -           bTwo, bDA,ccut, abin, rbin, top,             \
 -           bSelected, bDebug, stderr, nsel,             \
 -           bGem, oenv, fnm, fpnhb, trrStatus, natoms,   \
 -           status, nabin, nrbin, adist, rdist, debug)
 +            xkk, ykk, zkk, kcell, ak, k, bTric,         \
 +            bEdge_xjj, bEdge_yjj)                       \
 +    default(shared)
      {    /* Start of parallel region */
 -        threadNr = omp_get_thread_num();
 -#endif /* HAVE_OPENMP ================================================= */
 +        threadNr = gmx_omp_get_thread_num();
 +
          do
          {
 +            
              bTric = bBox && TRICLINIC(box);
  
 -#ifdef HAVE_OPENMP
 -            sync_hbdata(hb, p_hb[threadNr], nframes, t);
 +            if (bOMP)
 +            {
 +                sync_hbdata(hb, p_hb[threadNr], nframes, t);
 +            }
  #pragma omp single
 -#endif
              {
                  build_grid(hb,x,x[shatom], bBox,box,hbox, (rcut>r2cut)?rcut:r2cut, 
                             rshell, ngrid,grid);
                  if (hb->bDAnr)
                      count_da_grid(ngrid, grid, hb->danr[nframes]);
              } /* omp single */
 -#ifdef HAVE_OPENMP
 -            p_hb[threadNr]->time = hb->time; /* This pointer may have changed. */
 -#endif
 +
 +            if (bOMP)
 +            {
 +                p_hb[threadNr]->time = hb->time; /* This pointer may have changed. */
 +            }
 +
              if (bNN)
              {
  #ifdef HAVE_NN_LOOPS /* Unlock this feature when testing */
                  /* Loop over all atom pairs and estimate interaction energy */
 -#ifdef HAVE_OPENMP /* ------- */
 +
  #pragma omp single
 -#endif /* HAVE_OPENMP ------- */
                  {
                      addFramesNN(hb, nframes);
                  }
 -#ifdef HAVE_OPENMP /* ---------------- */
 +
  #pragma omp barrier
  #pragma omp for schedule(dynamic)
 -#endif /* HAVE_OPENMP ---------------- */
                  for (i=0; i<hb->d.nrd; i++)
                  {
                      for(j=0;j<hb->a.nra; j++)
              {
                  if (bSelected)
                  {
 -#ifdef HAVE_OPENMP
 +
  #pragma omp single
 -#endif
                      {
                          /* Do not parallelize this just yet. */
                          /* int ii; */
                  } /* if (bSelected) */
                  else
                  {
 -#ifdef HAVE_OPENMP
 +
  #pragma omp single
                      {
 -#endif
 -                    if (bGem)
 -                        calcBoxProjection(box, hb->per->P);
 +                        if (bGem)
 +                            calcBoxProjection(box, hb->per->P);
 +
 +                        /* loop over all gridcells (xi,yi,zi)      */
 +                        /* Removed confusing macro, DvdS 27/12/98  */
  
 -                    /* loop over all gridcells (xi,yi,zi)      */
 -                    /* Removed confusing macro, DvdS 27/12/98  */
 -#ifdef HAVE_OPENMP
                      }
                      /* The outer grid loop will have to do for now. */
  #pragma omp for schedule(dynamic)
 -#endif
                      for(xi=0; xi<ngrid[XX]; xi++)
                          for(yi=0; (yi<ngrid[YY]); yi++)
                              for(zi=0; (zi<ngrid[ZZ]); zi++) {
                                          i  = icell->atoms[ai];
                
                                          /* loop over all adjacent gridcells (xj,yj,zj) */
 -                                        /* This is a macro!!! */
 -                                        LOOPGRIDINNER(xj,yj,zj,xjj,yjj,zjj,xi,yi,zi,ngrid,bTric) {
 -                                            jcell=&(grid[zj][yj][xj].a[ogrp]);
 -                                            /* loop over acceptor atoms from other group (ogrp) 
 -                                             * in this adjacent gridcell (jcell) 
 -                                             */
 -                                            for (aj=0; (aj<jcell->nr); aj++) {
 -                                                j = jcell->atoms[aj];
 -                
 -                                                /* check if this once was a h-bond */
 -                                                peri = -1;
 -                                                ihb = is_hbond(__HBDATA,grp,ogrp,i,j,rcut,r2cut,ccut,x,bBox,box,
 -                                                               hbox,&dist,&ang,bDA,&h,bContact,bMerge,&peri);
 -                  
 -                                                if (ihb) {
 -                                                    /* add to index if not already there */
 -                                                    /* Add a hbond */
 -                                                    add_hbond(__HBDATA,i,j,h,grp,ogrp,nframes,bMerge,ihb,bContact,peri);
 -                    
 -                                                    /* make angle and distance distributions */
 -                                                    if (ihb == hbHB && !bContact) {
 -                                                        if (dist>rcut)
 -                                                            gmx_fatal(FARGS,"distance is higher than what is allowed for an hbond: %f",dist);
 -                                                        ang*=RAD2DEG;
 -                                                        __ADIST[(int)( ang/abin)]++;
 -                                                        __RDIST[(int)(dist/rbin)]++;
 -                                                        if (!bTwo) {
 -                                                            int id,ia;
 -                                                            if ((id = donor_index(&hb->d,grp,i)) == NOTSET)
 -                                                                gmx_fatal(FARGS,"Invalid donor %d",i);
 -                                                            if ((ia = acceptor_index(&hb->a,ogrp,j)) == NOTSET)
 -                                                                gmx_fatal(FARGS,"Invalid acceptor %d",j);
 -                                                            resdist=abs(top.atoms.atom[i].resind-
 -                                                                        top.atoms.atom[j].resind);
 -                                                            if (resdist >= max_hx)
 -                                                                resdist = max_hx-1;
 -                                                            __HBDATA->nhx[nframes][resdist]++;
 +                                        for(zjj = grid_loop_begin(ngrid[ZZ],zi,bTric,FALSE);
 +                                            zjj <= grid_loop_end(ngrid[ZZ],zi,bTric,FALSE);
 +                                            zjj++)
 +                                        {
 +                                            zj = grid_mod(zjj,ngrid[ZZ]);
 +                                            bEdge_yjj = (zj == 0) || (zj == ngrid[ZZ] - 1);
 +                                            for(yjj = grid_loop_begin(ngrid[YY],yi,bTric,bEdge_yjj);
 +                                                yjj <= grid_loop_end(ngrid[YY],yi,bTric,bEdge_yjj);
 +                                                yjj++)
 +                                            {
 +                                                yj = grid_mod(yjj,ngrid[YY]);
 +                                                bEdge_xjj =
 +                                                    (yj == 0) || (yj == ngrid[YY] - 1) ||
 +                                                    (zj == 0) || (zj == ngrid[ZZ] - 1);
 +                                                for(xjj = grid_loop_begin(ngrid[XX],xi,bTric,bEdge_xjj);
 +                                                    xjj <= grid_loop_end(ngrid[XX],xi,bTric,bEdge_xjj);
 +                                                    xjj++)
 +                                                {
 +                                                    xj = grid_mod(xjj,ngrid[XX]);
 +                                                    jcell=&(grid[zj][yj][xj].a[ogrp]);
 +                                                    /* loop over acceptor atoms from other group (ogrp) 
 +                                                     * in this adjacent gridcell (jcell) 
 +                                                     */
 +                                                    for (aj=0; (aj<jcell->nr); aj++) {
 +                                                        j = jcell->atoms[aj];
 +                                                        
 +                                                        /* check if this once was a h-bond */
 +                                                        peri = -1;
 +                                                        ihb = is_hbond(__HBDATA,grp,ogrp,i,j,rcut,r2cut,ccut,x,bBox,box,
 +                                                                       hbox,&dist,&ang,bDA,&h,bContact,bMerge,&peri);
 +                                                        
 +                                                        if (ihb) {
 +                                                            /* add to index if not already there */
 +                                                            /* Add a hbond */
 +                                                            add_hbond(__HBDATA,i,j,h,grp,ogrp,nframes,bMerge,ihb,bContact,peri);
 +                                                            
 +                                                            /* make angle and distance distributions */
 +                                                            if (ihb == hbHB && !bContact) {
 +                                                                if (dist>rcut)
 +                                                                    gmx_fatal(FARGS,"distance is higher than what is allowed for an hbond: %f",dist);
 +                                                                ang*=RAD2DEG;
 +                                                                __ADIST[(int)( ang/abin)]++;
 +                                                                __RDIST[(int)(dist/rbin)]++;
 +                                                                if (!bTwo) {
 +                                                                    int id,ia;
 +                                                                    if ((id = donor_index(&hb->d,grp,i)) == NOTSET)
 +                                                                        gmx_fatal(FARGS,"Invalid donor %d",i);
 +                                                                    if ((ia = acceptor_index(&hb->a,ogrp,j)) == NOTSET)
 +                                                                        gmx_fatal(FARGS,"Invalid acceptor %d",j);
 +                                                                    resdist=abs(top.atoms.atom[i].resind-
 +                                                                                top.atoms.atom[j].resind);
 +                                                                    if (resdist >= max_hx)
 +                                                                        resdist = max_hx-1;
 +                                                                    __HBDATA->nhx[nframes][resdist]++;
 +                                                                }
 +                                                            }
 +                                                            
                                                          }
 -                                                    }
 -
 -                                                }
 -                                            } /* for aj  */
 -                                        }
 -                                        ENDLOOPGRIDINNER;
 +                                                    } /* for aj  */
 +                                                } /* for xjj */
 +                                            } /* for yjj */
 +                                        } /* for zjj */
                                      } /* for ai  */
                                  } /* for grp */
                              } /* for xi,yi,zi */
                  } /* if (bSelected) {...} else */ 
  
 -#ifdef HAVE_OPENMP /* ---------------------------- */
 +
                  /* Better wait for all threads to finnish using x[] before updating it. */
 -                k = nframes;            /*         */
 -#pragma omp barrier                     /*         */
 -#pragma omp critical                    /*         */
 -                {                       /*         */
 +                k = nframes;
 +#pragma omp barrier
 +#pragma omp critical
 +                {
                      /* Sum up histograms and counts from p_hb[] into hb */
 -                    {                   /*         */
 +                    if (bOMP)
 +                    {
                          hb->nhb[k]   += p_hb[threadNr]->nhb[k];
                          hb->ndist[k] += p_hb[threadNr]->ndist[k];
 -                        for (j=0; j<max_hx; j++) /**/
 +                        for (j=0; j<max_hx; j++)
                              hb->nhx[k][j]  += p_hb[threadNr]->nhx[k][j];
 -                    }                   /*         */
 -                }                       /*         */
 -                /*                                 */
 +                    }
 +                }
 +
                  /* Here are a handful of single constructs
                   * to share the workload a bit. The most
                   * important one is of course the last one,
                   * where there's a potential bottleneck in form
                   * of slow I/O.                    */
 -#pragma omp single /* ++++++++++++++++,            */
 -#endif /* HAVE_OPENMP ----------------+------------*/
 -                { /*                  +   */
 -                    if (hb != NULL)  /*   */
 -                    { /*              +   */
 +#pragma omp barrier
 +#pragma omp single
 +                {
 +                    if (hb != NULL)
 +                    {
                          analyse_donor_props(opt2fn_null("-don",NFILE,fnm),hb,k,t,oenv);
 -                    } /*              +   */
 -                } /*                  +   */
 -#ifdef HAVE_OPENMP /*                 +   */
 -#pragma omp single /* +++           +++   */
 -#endif       /*                       +   */
 -                {  /*                 +   */
 -                    if (fpnhb)  /*    +   */
 +                    }
 +                }
 +
 +#pragma omp single
 +                {
 +                    if (fpnhb)
                          do_nhb_dist(fpnhb,hb,t);
 -                }  /*                 +   */
 +                }
              } /* if (bNN) {...} else  +   */
 -#ifdef HAVE_OPENMP /*                 +   */
 -#pragma omp single /* +++           +++   */
 -#endif       /*                       +   */
 -            {      /*                 +   */
 +
 +#pragma omp single
 +            {
                  trrStatus = (read_next_x(oenv,status,&t,natoms,x,box));
 -                nframes++;      /*    +   */
 -            }      /*                 +   */
 -#ifdef HAVE_OPENMP /* +++++++++++++++++   */
 +                nframes++;
 +            }
 +
  #pragma omp barrier
 -#endif
          } while (trrStatus);
  
 -#ifdef HAVE_OPENMP
 -#pragma omp critical
 +        if (bOMP)
          {
 -            hb->nrhb += p_hb[threadNr]->nrhb;
 -            hb->nrdist += p_hb[threadNr]->nrdist;
 -        }
 -        /* Free parallel datastructures */
 -        sfree(p_hb[threadNr]->nhb);
 -        sfree(p_hb[threadNr]->ndist);
 -        sfree(p_hb[threadNr]->nhx);
 +#pragma omp critical
 +            {
 +                hb->nrhb += p_hb[threadNr]->nrhb;
 +                hb->nrdist += p_hb[threadNr]->nrdist;
 +            }
 +            /* Free parallel datastructures */
 +            sfree(p_hb[threadNr]->nhb);
 +            sfree(p_hb[threadNr]->ndist);
 +            sfree(p_hb[threadNr]->nhx);
  
  #pragma omp for
 -        for (i=0; i<nabin; i++)
 -            for (j=0; j<actual_nThreads; j++)
 +            for (i=0; i<nabin; i++)
 +                for (j=0; j<actual_nThreads; j++)
  
 -                adist[i] += p_adist[j][i];
 +                    adist[i] += p_adist[j][i];
  #pragma omp for
 -        for (i=0; i<=nrbin; i++)
 -            for (j=0; j<actual_nThreads; j++)
 -                rdist[i] += p_rdist[j][i];
 +            for (i=0; i<=nrbin; i++)
 +                for (j=0; j<actual_nThreads; j++)
 +                    rdist[i] += p_rdist[j][i];
      
 -        sfree(p_adist[threadNr]);
 -        sfree(p_rdist[threadNr]);
 +            sfree(p_adist[threadNr]);
 +            sfree(p_rdist[threadNr]);
 +        }
      } /* End of parallel region */
 -    sfree(p_adist);
 -    sfree(p_rdist);
 -#endif
 +    if (bOMP)
 +    {
 +        sfree(p_adist);
 +        sfree(p_rdist);
 +    }
    
      if(nframes <2 && (opt2bSet("-ac",NFILE,fnm) || opt2bSet("-life",NFILE,fnm)))
      {
          if (opt2bSet("-hbm",NFILE,fnm)) {
              t_matrix mat;
              int id,ia,hh,x,y;
-       
-             mat.nx=nframes;
-             mat.ny=hb->nrhb;
-             snew(mat.matrix,mat.nx);
-             for(x=0; (x<mat.nx); x++) 
-                 snew(mat.matrix[x],mat.ny);
-             y=0;
-             for(id=0; (id<hb->d.nrd); id++) 
-                 for(ia=0; (ia<hb->a.nra); ia++) {
-                     for(hh=0; (hh<hb->maxhydro); hh++) {
-                         if (hb->hbmap[id][ia]) {
-                             if (ISHB(hb->hbmap[id][ia]->history[hh])) {
-                                 /* Changed '<' into '<=' in the for-statement below.
-                                  * It fixed the previously undiscovered bug that caused
-                                  * the last occurance of an hbond/contact to not be
-                                  * set in mat.matrix. Have a look at any old -hbm-output
-                                  * and you will notice that the last column is allways empty.
-                                  * - Erik Marklund May 30, 2006
-                                  */
-                                 for(x=0; (x<=hb->hbmap[id][ia]->nframes); x++) {
-                                     int nn0 = hb->hbmap[id][ia]->n0;
-                                     range_check(y,0,mat.ny);
-                                     mat.matrix[x+nn0][y] = is_hb(hb->hbmap[id][ia]->h[hh],x);
+             
+             if ((nframes > 0) && (hb->nrhb > 0))
+             {
+                 mat.nx=nframes;
+                 mat.ny=hb->nrhb;
+                 
+                 snew(mat.matrix,mat.nx);
+                 for(x=0; (x<mat.nx); x++) 
+                     snew(mat.matrix[x],mat.ny);
+                 y=0;
+                 for(id=0; (id<hb->d.nrd); id++) 
+                     for(ia=0; (ia<hb->a.nra); ia++) {
+                         for(hh=0; (hh<hb->maxhydro); hh++) {
+                             if (hb->hbmap[id][ia]) {
+                                 if (ISHB(hb->hbmap[id][ia]->history[hh])) {
+                                     /* Changed '<' into '<=' in the for-statement below.
+                                      * It fixed the previously undiscovered bug that caused
+                                      * the last occurance of an hbond/contact to not be
+                                      * set in mat.matrix. Have a look at any old -hbm-output
+                                      * and you will notice that the last column is allways empty.
+                                      * - Erik Marklund May 30, 2006
+                                      */
+                                     for(x=0; (x<=hb->hbmap[id][ia]->nframes); x++) {
+                                         int nn0 = hb->hbmap[id][ia]->n0;
+                                         range_check(y,0,mat.ny);
+                                         mat.matrix[x+nn0][y] = is_hb(hb->hbmap[id][ia]->h[hh],x);
+                                     }
+                                     y++;
                                  }
-                                 y++;
                              }
                          }
                      }
+                 mat.axis_x=hb->time;
+                 snew(mat.axis_y,mat.ny);
+                 for(j=0; j<mat.ny; j++)
+                     mat.axis_y[j]=j;
+                 sprintf(mat.title,bContact ? "Contact Existence Map":
+                         "Hydrogen Bond Existence Map");
+                 sprintf(mat.legend,bContact ? "Contacts" : "Hydrogen Bonds");
+                 sprintf(mat.label_x,"%s",output_env_get_xvgr_tlabel(oenv));
+                 sprintf(mat.label_y, bContact ? "Contact Index" : "Hydrogen Bond Index");
+                 mat.bDiscrete=TRUE;
+                 mat.nmap=2;
+                 snew(mat.map,mat.nmap);
+                 for(i=0; i<mat.nmap; i++) {
+                     mat.map[i].code.c1=hbmap[i];
+                     mat.map[i].desc=hbdesc[i];
+                     mat.map[i].rgb=hbrgb[i];
                  }
-             mat.axis_x=hb->time;
-             snew(mat.axis_y,mat.ny);
-             for(j=0; j<mat.ny; j++)
-                 mat.axis_y[j]=j;
-             sprintf(mat.title,bContact ? "Contact Existence Map":
-                     "Hydrogen Bond Existence Map");
-             sprintf(mat.legend,bContact ? "Contacts" : "Hydrogen Bonds");
-             sprintf(mat.label_x,"%s",output_env_get_xvgr_tlabel(oenv));
-             sprintf(mat.label_y, bContact ? "Contact Index" : "Hydrogen Bond Index");
-             mat.bDiscrete=TRUE;
-             mat.nmap=2;
-             snew(mat.map,mat.nmap);
-             for(i=0; i<mat.nmap; i++) {
-                 mat.map[i].code.c1=hbmap[i];
-                 mat.map[i].desc=hbdesc[i];
-                 mat.map[i].rgb=hbrgb[i];
+                 fp = opt2FILE("-hbm",NFILE,fnm,"w");
+                 write_xpm_m(fp, mat);
+                 ffclose(fp);
+                 for(x=0; x<mat.nx; x++)
+                     sfree(mat.matrix[x]);
+                 sfree(mat.axis_y);
+                 sfree(mat.matrix);
+                 sfree(mat.map);
+             }
+             else 
+             {
+                 fprintf(stderr,"No hydrogen bonds/contacts found. No hydrogen bond map will be printed.\n");
              }
-             fp = opt2FILE("-hbm",NFILE,fnm,"w");
-             write_xpm_m(fp, mat);
-             ffclose(fp);
-             for(x=0; x<mat.nx; x++)
-                 sfree(mat.matrix[x]);
-             sfree(mat.axis_y);
-             sfree(mat.matrix);
-             sfree(mat.map);
          }
      }