-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)
# 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)
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)
"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)
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
########################################################################
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)
########################################################################
#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)
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)
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)
########################################################################
# 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)
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})
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
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)
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)
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)
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)
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)
#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
/* 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
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+#include "gmx_header_config.h"
#include <stdio.h>
#include <stdlib.h>
#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
#include "statutil.h"
-#ifdef GMX_THREADS
+#ifdef GMX_THREAD_MPI
#include "thread_mpi.h"
#endif
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;
{
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
}
#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
}
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;
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
{
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;
gmx_bool bRead;
int bs;
+ if (file == NULL)
+ {
+ return NULL;
+ }
+
if (mode[0]=='w') {
make_backup(file);
}
{
#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;
*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)
{
rc = EINVAL;
}
-#elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
+#elif (defined GMX_NATIVE_WINDOWS)
if(gmxdir!=NULL)
{
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,
*/
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);
/* 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)
* 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);
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
#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 {
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");
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:
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:
#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"
{"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))
/* 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");
E = 0;
hb->hbE.E[d][a][h][frame] = E;
-#ifdef HAVE_OPENMP
+
#pragma omp critical
-#endif
{
hb->hbE.Etot[frame] += E;
}
}
}
+
}
static void inc_nhbonds(t_donors *ddd,int d, int h)
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];
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);
}
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;
* 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)
{
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;
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)
"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);
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);
}
}